« October 2006 »
SunMonTueWedThuFriSat
   
2
4
5
6
7
8
9
10
12
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
  
       
Today
XML

Blog::Navigation

GetJava Download Button
Get the Source
Personal Blog

Blog::Referers

Today's Page Hits: 21

Powered by Roller Weblogger.
« Previous month (Sep 2006) | Main | Next month (Nov 2006) »
20061114 Tuesday November 14, 2006

Javac Tree API - check for empty catch blocks

I wrote about javac's APIs in my last blog entry. But, I did not mention an example for Javac's Tree API. How about a simple example that uses javac's tree API? Here it is... In the following example, we implement a checker for empty catch blocks (because "eating exceptions silently" is considered bad) and warn the user.

We implement EmptyCatchChecker as a JSR-269 processor. In the process method, we get each ClassTree node and run it through a verifier visitor - which is a TreeScanner. In the TreeScanner subclass, whenever CatchTree node is visited, we check whether it's block has any statements or not. If not, we issue a warning message. To give a better warning message, we print the class and the method in which empty catch block occurs [To print source file and line number, we need CompilationUnitTree and I don't know how to get that!].

Update: I had missed HTML escaping < characters in source code [for generics] and so the code below was not compiling. Thanks to Jaya Hangal for notifying this issue. I've fixed it now.


import java.util.*;

// import all JSR 199, JSR 269 and Tree API stuff
import javax.annotation.processing.*;
import javax.lang.model.*;
import javax.lang.model.element.*;
import javax.lang.model.type.*;
import javax.tools.*;

import com.sun.source.tree.*;
import com.sun.source.util.*;

// An annotation processor that processes all classes
@SupportedAnnotationTypes("*")
@SupportedSourceVersion(SourceVersion.RELEASE_6)
public class EmptyCatchChecker extends AbstractProcessor {
    private Trees treeUtils;
   
    public void init(ProcessingEnvironment pe) {
        super.init(pe);
        treeUtils = Trees.instance(pe);
    }

    public boolean process(Set<? extends TypeElement> annotations,
                           RoundEnvironment roundEnv) {
        if (! roundEnv.processingOver()) {
            Set<? extends Element> elements =
                roundEnv.getRootElements();

            for (Element e: elements) {
                Tree tree = treeUtils.getTree(e);                
                if (tree.getKind().equals(Tree.Kind.CLASS)) {
                    verify((ClassTree)tree);
                }
            }
        }
        return true;
    }

    // verify each class tree
    private void verify(ClassTree ct) {
        ct.accept(new TreeScanner<Object, Void>() {
            private String currentClass, currentMethod;

            public Object visitClass(ClassTree node, Void v) {
                currentClass = node.getSimpleName().toString();
                return super.visitClass(node, v);
            }

            public Object visitMethod(MethodTree node, Void v) {
                currentMethod = node.getName().toString();
                return super.visitMethod(node, v);
            }

            public Object visitCatch(CatchTree node, Void v) {
                BlockTree block = node.getBlock();
                if (block.getStatements().isEmpty()) {
                    warn("empty catch block in " + currentMethod +
                       " method of " + currentClass);
                }                 
                return super.visitCatch(node, v);
            }
        }, null);
    }

    private void warn(String msg) {
        processingEnv.getMessager().printMessage(Diagnostic.Kind.WARNING, msg);
    }
}

To compile the above code, you can use the following command:


javac -classpath $JDK_HOME/lib/tools.jar EmptyCatchChecker.java

To use this empty catch checker, you can use the following command:

javac -processor EmptyCatchChecker YourClass.java

Note that the above checker can be fooled by adding a simple ';' in catch block - because ';' is a statement. How do we check for that? That is an exercise to the reader ;-) [Hint: EmptyStatementTree]



( Nov 14 2006, 09:07:55 PM IST ) Permalink Comments [3] del.icio.us | furl | simpy | slashdot | technorati | digg

20061113 Monday November 13, 2006

Learning javac's APIs

There are three APIs of javac:



( Nov 13 2006, 09:09:14 PM IST ) Permalink del.icio.us | furl | simpy | slashdot | technorati | digg

20061111 Saturday November 11, 2006

Applet-JAX and scripting

I came across Chet Hasse's blog entry titled "Applet-JAX ". In the code, he uses Java-to-Javascript Communication. If you are going to use JDK 6, then you can use scripting API (javax.script) to access browser's (native) JavaScript script engine. JSR-223 script engine for browser's JS interpreter is available at https://scripting.dev.java.net/. With JDK 6, Rhino based JSR-223 engine is included as well. There is also scriptlet applet to write applets in JavaScript.



( Nov 11 2006, 10:48:37 AM IST ) Permalink Comments [3] del.icio.us | furl | simpy | slashdot | technorati | digg

20061103 Friday November 03, 2006

JDK source: jhat

If you have downloaded JDK source from jdk6.dev.java.net, the sources for jhat (Java Heap Analysis Tool) is under $JDK/j2se/src/share/classes/com/sun/tools/hat directory. There is an ant build file (build.xml) to build just the jhat (jhat.jar is the build output). I mentioned about Object Query Language (SQL-like language to query Java Heap) support for jhat - you may want to refer to the following:

OQL is implemented using the JavaScript JSR-223 engine in JDK 6. select...from...where is parsed by a simple tokenizer. select and where expressions are JavaScript expressions. Also, if anything that does not start with "select" is directly "eval"-ed as JavaScript. You can use OQL form to write JavaScript functions - which you can call in subsequent OQL queries.



( Nov 03 2006, 06:34:13 PM IST ) Permalink del.icio.us | furl | simpy | slashdot | technorati | digg

20061101 Wednesday November 01, 2006

HotSpot source: Serviceability Agent

The HotSpot Serviceability Agent (SA) is a set of APIs and tools for debugging HotSpot Virtual Machine. Unlike most previous debugging systems that assume a "cooperative" model in which the target process runs code to assist in the debugging process, the SA requires no code to be run in the target VM. The HotSpot SA uses primitives like symbol lookup and reading of process memory to implement its functionality. Because of that, HotSpot SA can work on core dumps as well. You may want to read this (somewhat dated, but still useful) paper - The HotSpot Serviceability Agent: An out-of-process high level debugger for a Java virtual machine.

Now, coming to the source code: In the source download from jdk6.dev.java.net, you may want to look at $JDK/hotspot/agent directory. There is some documentation of SA under $JDK/hotspot/agent/doc directory. The following tools are using SA.

Starting from JDK 6, for live processes, (few of) these tools (under few options) use attach-on-demand.



( Nov 01 2006, 06:31:39 PM IST ) Permalink del.icio.us | furl | simpy | slashdot | technorati | digg

Copyright (C) 2005, A. Sundararajan's Weblog