Java 6 Compiler API

Java SE 6 was released earlier today. The list of improvements contains many new APIs, including scripting support (with built-in Javascript support via Rhino), JDBC 4.0, the Java Compiler API, and the Compiler Tree API.

The Java Compiler API provides an abstraction for Java compilers, while the Compiler Tree API provides direct access to javac’s AST. Sorcerer is a powerful source code browser generator based on the tree API, and I guess many more cool tools will follow.

I haven’t looked into either API too hard yet, but at least managed to come up with a trivial program that invokes javac on a given file:

JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
StandardJavaFileManager manager = compiler.getStandardFileManager(null, null, null);
Iterable compilationUnits = manager.getJavaFileObjects(new File("MyClass.java"));
compiler.getTask(null, manager, null, null, null, compilationUnits).call();
manager.close();

Besides being overly explicit for this rather trivial task (perhaps I missed a shortcut), it “just works” and makes life for anyone needing to compile some java files much easier.

Advertisements

2 Comments »

  1. Leon Nemets said

    This may not be the right forum but since Java Compiler API is so new I haven’t been able to find much information.
    I have managed to get the example code to work as well but it is still relies on reading and writing to files (very slow).
    I am wondering whether there is a method to avoid reading source files and compiling from a stringstream for example, and having the compiled output not written out to a file as well (in-process/in-memory)

    Regards,
    Leon Nemets

  2. Hi Leon,
    interesting question. It turns out that the Jasper JSP compiler already uses Mustang for in-memory compilation. Take a look at https://maven-repository.dev.java.net/repository/jasper-jsr199/java-sources/jasper-jsr199-9.1-sources.jar

    Using in-memory sources as input is simple, just create a SimpleJavaFileObject that returns the source:

    final String source = “class test123 ….”;
    JavaFileObject[] compilationUnits = { new SimpleJavaFileObject(
    URI.create(“string://test123”), JavaFileObject.Kind.SOURCE) {
    public CharSequence getCharContent(boolean ignore) {
    return source;
    }
    } };

    This creates the .class file in the current directory. Creating memory output streams seems to be slightly more complex, take a look at the Jasper source to see how it’s done.

RSS feed for comments on this post · TrackBack URI

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: