Skip to main content

See Java code the way javac sees it

Posted by timboudreau on February 28, 2008 at 3:50 PM PST

I wrote a small Swing app to browse javac's abstract syntax trees (ASTs) of source code. If you've ever wanted to write a tool that analyzes Java source code, it is a big help for understanding the Javac tree API.

Last spring I set about learning javac's Tree API (JSR 199) - NetBeans uses it internally as its parser for Java source code. It has a bit of a learning curve, and contains lots of this-tree and that-tree interfaces for different types of structures in Java source code. So to help me develop an intuitive understanding of what all of these classes map to, I wrote a tool - a standalone Swing app that lets you open a Java source file and then browse its AST.



syntaxtreebrowser.jpg



The tree on the left lets you drill through the syntax tree itself. The middle pane shows you the object that is selected, and a tree of all of its fields and methods via introspection, which you can drill as deeply as you want through. The right pane is sensitive to selection in whichever of the other two panes has focus. The top half shows you the list of all types the selected object implements (and boldfaces those that are part of the official API), and the bottom half shows you the value of toString() for the selected object (if it's part of the syntax tree, it will be the source code text).

I found it very useful, and still use it to figure out just how to hunt down a particular thing I want to find in source code. Hopefully it will inspire some others to play with javac as well. It requires JDK 6. You can download the JAR file here and just run it with java -jar.

The source code is available in NetBeans CVS under contrib/SyntaxTreeNavigator (everything was reorganized for the recent migration to Mercurial, and I haven't figured out where it is in the new source structure yet).Update (3/31/08): I've set up a java.net project for the source code, syntaxtreebrowser.dev.java.net. It is pending approval but it should be publicly visible in a few days.

Caveats: (updated 2/29/07)

  1. To use the application, you will need javac on your classpath. If you are running Apple's JDK 1.6 it already is. For other platforms you may need to run with -Xbootclasspath/p:/PATH/TO/javac.jar (may be in tools.jar).
  2. This application uses the com.sun.source.tree API from javac. If you are not running Sun's javac, this package will probably not be there.

I have updated the JAR file to produce better diagnostic information, and added a source zip file.

Related Topics >>

Comments

Update 2014: The java.net project appears to have been ...

Update 2014: The java.net project appears to have been deleted in a java.net migration. I've asked the java.net folks for help with it and am waiting for a response.

In the meantime, if anybody has a source checkout of this they could tar up, it would be appreciated.

When you download this the compiler complains that it can't ...

When you download this the compiler complains that it can't find com.sun..... packages.... these are in tools.jar but there's no mention that we have to include tools.jar on our classpath. Is there something I am missing ? Many thanks, great contribution!!

Tim,
Seems you can never make something cool available without getting hit with a bunch of RFEs...

You're exposing all the internals of the JC* classes. It would be nice to have a checkbox to let me only see the public JSR-199 compliant data. Should be a matter of looping through all the methods of the *Tree interface rather than all the public get() methods in the class.

Also, looks like you display the class name at each node in the tree. For example, in a class with no "extends" or "implements" clauses, I get two empty "ExtendsClause" nodes under JCClassDecl. One is from the getExtendsClause() method and the other is from the getImplementsClause() method. It would be nice to both the name of the method called ("getImplementsClause()") as well as the actual class name of the objects returned ("ExtendsClause").

I'll see if I can get time to make these enhancements myself this weekend.

Again, thanks for the very nice tool.

By all means, if you feel like sending me a patch, I'd be happy to incorporate it.

Hi Again,
I did write a replacement class that does the things I mention above. It's called JavacASTTreeNode, and it's a direct replacement for your "V" class. It displays method names rather than class types, so for example, you'll see "getExtendsClause()" and "getImplementsClause()" nodes in the tree, rather than two "ExtendsClause" nodes. Also, it only does introspection on the JSR-199 "Tree" interfaces, so you'll see the standard "ClassTree" rather than the sun-internal "JCClassDecl".

Anyone let me know if this interests you.

Andy

Hi Tim, Including tools.jar in my bootclasspath as you suggested works. Thanks! The tool looks very nice, especially for just getting started using the compiler API. For anyone else who's just starting to use this API, it might help to realize that the official public API, JSR-199, contains almost all interfaces, such as CompilationUnitTree. These are in the com.sun.source.tree package, and the javadoc is here But the Sun-compiler-specific classes that implement those interfaces, such as JCCompilationUnit, are all defined as inner classes of the JCTree class in the com.sun.tools.javac.tree package. You won't find the Javadoc for those classes anywhere, as they're "Sun internal", and you'll have to download the JDK6 source and run javadoc yourself. They're in directory /langtools/src/share/classes/com/sun/tools/javac

Sources are now available in the attached zip file, and I've updated the JAR file to provide better diagnostic messages for the issues mentioned.

hi Tim,

Can you put the tools' source someplace so that I can debug it in my IDE ? It would be nice if you could create a netbeans IDE project for the same.

Atleast a source jar will help. I'm using JDK 1.6._03. from sun.

Thank you,

BR,
~A

Based on what I read here the javac tree api is supposed to work only with the sun compiler. Could the errors reported above be due to the usage of non sun java compilers?
From the interview: In addition, Sun is providing access to the compiler syntax tree, a feature relied on very heavily by the upcoming version of NetBeans. While this is not directly in JSR 199, we're providing that capability in subclasses of the 199 API. At the moment, this only works on Sun's compiler, but providing standardized access to a tree API is something we might want to consider in the future.

This would be useful when hacking the compiler. Each pass of the compiler modifies the AST (especially Lower.java), and it can be difficult to understand what's going on. You could hand the top-level node to this tool, which would run in a separate thread, and have "breakpoints" in the compiler code that block the main compiler thread, allowing the UI to browse the current state of the tree as various transformations mangle it.

Mariso: This would be caused by ToolProvider.getSystemJavaCompiler(); returning null. Are you running with a Sun JDK or something else? AFAIK, that should not return null...

Anjanb2: A window should open after you choose the source file.

Okay, this is more difficult than it looked...

it throws NPE when I try to open a file: Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException at syntaxtreenavigator.SyntaxTreeVisualizer.openFile(SyntaxTreeVisualize r.java:179) at syntaxtreenavigator.SyntaxTreeVisualizer.openMenuItemActionPerformed( SyntaxTreeVisualizer.java:153) at syntaxtreenavigator.SyntaxTreeVisualizer.run(SyntaxTreeVisualizer.jav a:62)

Source code is now in cvs there.

FYI, I've created a java.net project for this code - https://syntaxtreebrowser.dev.java.net/ - it should be up in a day or two, once it gets approved. Contributions welcome.

I am a student at the technical university of munich in computer sience. Most times we do development with java in classes. So this tool seems to be very helpful for understanding. I just downloaded it and will test it. Thanks for sharing.

Very interesting post, I will try what you wrote here. MyBlog:

hi tim,

I tried this on HelloWorld.java :( just a static method), I did NOT see any output from the program.

Was there something that is expected of the user after pointing out the java source file through the dialog box ?

thank you,
BR,
~A

Oh, and thanks much for the links!

Andy: Argh, I'll bet it's me and my mac. That is, Apple puts everything on the classpath; other platforms probably don't have javac on the bootclasspath. Adding it to your bootclasspath should fix it. Also, if someone attempts to run it against the JRE, not full JDK, it's going to be unhappy. Re hg, hg is working just fine. hg pull http://hg.netbeans.org/main/ should get the sources. Out of date ones should still be available in CVS I think; you might have to pass a sticky date from before hg migration - the CVS server will stick around for some time because people still have work on branches and such, and history was not migrated for deleted things. Sorry for any confusion :-/ -Tim

Woot!

Just as I posted, pepe posted the same problem :) Nice to know it's not me and my CLASSPATH. Now I'm really curious as to what sort of stunt you're trying to pull on us at line 187 of SyntaxTreeVisualizer.java :) Andy

Hi Tim,

When downloading Netbeans 6.0 using CVS with the instructions here, If I use the -P option, I get no files at all and only a top-level file called MOVED that says everything's moved to hg. Without -P, I just get empty directories.

Isn't mercurial still "non-functional"? If so, seems like there's no good way to get the source and maybe you could just post a link to a file with the source for us :)

When trying to run it, I get a NoClassDefFoundError for com/sun/tools/javac/api/JavacTaskImpl class. Strange, because when I run it with -verbose:classes, I see that other classes (including JavacTaskImpl$2) are being loaded just fine from my tools.jar. I'm using JDK 1.6.0_10-ea with cygwin. I feel like a newbie again tracking down CLASSPATH problems.

Anyhow, I thought I'd mention it, as the other poster may be having the same problem.

Here are a few Java graph layout engines:
http://www.yworks.com/en/products_yfiles_about.htm
http://jung.sourceforge.net/pmwiki/index.php/Main/ImageGallery
http://www.jgraph.com/layout.html
Andy

Hello.
The application is looking for a missing class in my jdk6.
Exception in thread "AWT-EventQueue-0" java.lang.NoClassDefFoundError: com/sun/tools/javac/api/JavacTaskImpl at syntaxtreenavigator.SyntaxTreeVisualizer.openFile(SyntaxTreeVisualizer.java:187) at syntaxtreenavigator.SyntaxTreeVisualizer.openMenuItemActionPerformed(SyntaxTreeVisualizer.java:153) at syntaxtreenavigator.SyntaxTreeVisualizer.run(SyntaxTreeVisualizer.java:62) at java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:209) at java.awt.EventQueue.dispatchEvent(EventQueue.java:597) at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:273) at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:183) at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:173) at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:168) at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:160) at java.awt.EventDispatchThread.run(EventDispatchThread.java:121)
That is a very interesting utility, by the way. I have been wanting to play with AST for long. This might be a start once i make it work.

hi tim,

after I tried this on HelloWorld.java : just a static method, I did NOT see any output from the program.

Was there something that is expected of the user after pointing out the java source file through the dialog box ?

thank you,

BR,
~A

Tim,
"Last spring I set about learning javac's Tree API (JSR 199)"
The Tree API is not JSR 199. They are closely related (along with JSR 269) but not the same.