Incremental java compile AKA javac print compile dependencies

Jonathan Gibbons jonathan.gibbons at oracle.com
Fri May 28 08:28:33 PDT 2010


On 05/27/2010 11:36 PM, Joshua Maurice wrote:
> On Thu, May 27, 2010 at 11:33 AM, Jonathan Gibbons 
> <jonathan.gibbons at oracle.com <mailto:jonathan.gibbons at oracle.com>> wrote:
>
>     On 05/27/2010 12:20 AM, Joshua Maurice wrote:
>
>         Thank you again, but do you know any good examples of those
>         APIs? I am unable to quickly find some good documentation or
>         examples on Types, type mirrors, and such.
>
>
>     For docs, start with
>     http://java.sun.com/javase/6/docs/technotes/guides/javac/index.html
>
>     Roughly speaking, once you get to the point of being able to call
>     parse() and analyze() ...
>
>     -- walk the trees with a TreeScanner
>        -- you're looking for nodes which reference other classes; this
>     mostly means you need to look for declarations and expressions
>
>     -- expressions have a type (TypeMirror), from a type you want to
>     get to its element.
>        -- a type is an "instance", like List<String>, an element is an
>     entity in the source and is like a decl of a family of types, like
>     List<T>
>        -- move between types and elements using the Types and Elements
>     utility APIs
>
>     -- from an element, use getEnclosingElement to get to the element
>     that you wish to record a dependency on
>        -- e.g. your class might use X.foo, but you might want to
>     record a dependency on class X, not field foo.
>
>     -- from an element, if you need to you can get to its tree (via
>     Trees.getTree) or its compilation unit (via Trees.getPath)
>
>     -- from a compilation unit, you can get the source file
>
>     And Robert's your father's brother.
>
>
> Well, thank you again sir. Through some random googling, I managed to 
> whip up the file at the end, which is near exactly what I need, I 
> think. With this, my experimental build system is outperforming my 
> company's current Maven solution for a full clean rebuild by a factor 
> of 4 or 5. The incremental build is so fast I'm not even sure it's 
> correct! (Further testing is in order.)

Well done.

>
> Also, if / when that JavacTask.generate bug gets fixed, my profiling 
> indicates that it may speed it up by another 40% or so. (At least, 
> it's taking ~40% of the CPU time in the extra parse and analyze calls 
> according to the profiler YourKit.)
>
> Relevant code to get compile dependencies for a java file. Note that I 
> think you have to close the result transitively over all super types 
> to get accurate results (in addition to Ghost Dependencies).

You should only need to look at the API signatures of any files not 
listed on the command line.  There should be no need to look inside 
method bodies of any files you are not compiling, so if you're looking 
at them with a tree scanner, you can optimise away the scan of the 
method body.



>
>
> package com.informatica.devops.jicb.incr_java;
>
> import java.util.HashSet;
> import java.util.Set;
>
> import javax.lang.model.element.Element;
> import javax.lang.model.element.ElementKind;
>
> import com.sun.source.tree.CompilationUnitTree;
> import com.sun.source.tree.Tree;
> import com.sun.source.util.TreeScanner;
> import com.sun.tools.javac.tree.JCTree;
> import com.sun.tools.javac.tree.TreeInfo;
>
> public class CompileDependencies {
>     //must call this after JavacTask.analyze to get useful information
>     public static Set<String> get(final CompilationUnitTree tree) {
>         final Visitor visitor = new Visitor();
>         visitor.scan(tree, null);
>         return visitor.fullNamesOfAllFoundTypes;
>     }
>
>     private static class Visitor extends TreeScanner<Void, Void> {
>         public final Set<String> fullNamesOfAllFoundTypes = new 
> HashSet<String>();
>         @Override public Void scan(Tree node, Void v) {
>             if (node != null) {
>                 Element ele = TreeInfo.symbol((JCTree)node);
>                 for ( ; ele != null; ele = ele.getEnclosingElement()) {
>                     final ElementKind kind = ele.getKind();
>                     if (ElementKind.CLASS == kind
>                             || ElementKind.INTERFACE == kind
>                             || ElementKind.ANNOTATION_TYPE == kind
>                             || ElementKind.ENUM == kind) {
>                         fullNamesOfAllFoundTypes.add(ele.toString());
>                     }
>                 }
>             }
>             super.scan(node, null);
>             return null;
>         }
>     }
> }

-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://mail.openjdk.java.net/pipermail/compiler-dev/attachments/20100528/617abead/attachment.html 


More information about the compiler-dev mailing list