X

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

Join the discussion

Comments ( 4 )
  • aaaaa Tuesday, May 27, 2008

    I want stady from this site


  • Murad Islam Thursday, June 5, 2008

    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.


  • Dana Nourie Thursday, June 5, 2008

    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


  • guest Friday, June 13, 2008

    it was useful tip


Please enter your name.Please provide a valid email address.Please enter a comment.CAPTCHA challenge response provided was incorrect. Please try again.Captcha
Oracle

Integrated Cloud Applications & Platform Services