Source Code Analysis Using Java 6 APIs

by Seema Richard, Deepa Sobhana

Have you ever thought of how tools like Checkstyle or FindBugs perform a static code analysis, or how Integrated Development Environments (IDEs) like NetBeans or Eclipse execute quick code fixes or find the exact references of a field declared in your code? In many cases, IDEs have their own APIs to parse the source code and generate a standard tree structure, called an Abstract Syntax Tree (AST) or "parse tree," which can be used for deeper analysis of the source elements. The good news is that it is now possible to accomplish the said tasks plus a lot more with the help of three new APIs introduced in Java as part of the Java Standard Edition 6 release. The APIs that might be of interest to developers of Java applications that need to perform source code analysis are the Java Compiler API (JSR 199), the Pluggable Annotation Processing API (JSR 269), and the Compiler Tree API.

In this article, we explore the features of each of these APIs and go on to develop a simple demo application that verifies certain Java coding rules on a set of source code files supplied as input. This utility also shows the coding violation messages as well as the location of violated source code as output. Consider a simple Java class that overrides the equals() method of the Object class. The coding rule to be verified is that every class that implements the equals() method should also override the hashcode() method with the proper signature. You can see that the TestClass class below does not define the hashcode() method, even though it has the equals() method.

 

public class TestClass implements Serializable {
int num;

@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if ((obj == null) || (obj.getClass() != this.getClass()))
return false;
TestClass test = (TestClass) obj;
return num == test.num;
}
}

Let us go on and analyze this class as part of the build process with the help of these three APIs.

Invoking the Compiler from Code: The Java Compiler API

We all use the javac command-line tool for compiling Java source files to class files. Then why do we need an API to compile Java files? Well, the answer is quite simple: as the name describes, this new standard API lets us invoke the compiler from our own Java applications; i.e., you can programmatically interact with the compiler and thereby make compilation part of application-level services. Some typical uses of this API are listed below.

  • The compiler API helps application servers to minimize the time taken to deploy applications, for example, by avoiding the overhead of using an external compiler for compiling the servlet sources generated from the JSP pages.

  • Developer tools like IDEs and code analyzers can invoke the compiler from within the editor or build tools that significantly reduce the compile time.

The Java compiler classes are packaged under the javax.tools package. The ToolProvider class of this package provides a method called getSystemJavaCompiler() that returns an instance of some class that implements the JavaCompiler interface. This compiler instance can be used to create a compilation task that will perform the actual compilation. The Java source files to be compiled will be then passed to the compilation task. For this, the compiler API provides a file manager abstraction called JavaFileManager, which allows Java files to be retrieved from various sources, such as the file system, databases, memory, and so on. In this sample, we use StandardFileManager, a file manager based on java.io.File. The standard file manager can be acquired by calling the getStandardFileManager() method of the JavaCompiler instance. The code snippet for the above-mentioned steps is shown below:

//Get an instance of java compiler
JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();

//Get a new instance of the standard file manager implementation
StandardJavaFileManager fileManager = compiler.
getStandardFileManager(null, null, null);

// Get the list of java file objects, in this case we have only
// one file, TestClass.java
Iterable compilationUnits1 =
fileManager.getJavaFileObjectsFromFiles("TestClass.java");



A diagnostic listener can be optionally passed to the getStandardFileManager() method to produce diagnostic reports of any non-fatal problems. In this code snippet, we pass null values, since we are not collecting the diagnostics from the tool. For details of the other parameters passed to these methods, please refer to the Java 6 API. The getJavaFileObjectsfromFiles() method of the StandardJavaFileManager returns all the JavaFileObject instances that correspond to the supplied Java source files.

Read the rest of this article

Comments:

I want stady from this site

Posted by aaaaa on May 27, 2008 at 06:45 AM PDT #

I want to learn java programming from the beginning.Actually I hold no idea on this subject.So it would be great to if I am able to get trained from your class.

Posted by Murad Islam on June 04, 2008 at 11:22 PM PDT #

If you want to learn Java programming from the beginning, I recommend you read Java Technology Fundamentals and use the New to Java Programming Center, where you can find many tutorials:

http://blogs.sun.com/JavaFundamentals/

http://java.sun.com/new2java/

Dana Nourie

Posted by Dana Nourie on June 05, 2008 at 02:24 AM PDT #

it was useful tip

Posted by guest on June 12, 2008 at 08:16 PM PDT #

Post a Comment:
Comments are closed for this entry.
About

John O'Conner

Search

Categories
Archives
« April 2014
SunMonTueWedThuFriSat
  
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
   
       
Today