JavacTask.generate bug?

Jonathan Gibbons jonathan.gibbons at oracle.com
Thu May 27 16:44:24 PDT 2010


I don't know of any bugs in this area.     You could try setting 
-XDverboseCompilePolicy which is an undocumented option to trace the 
compiler's operation.

javac will stop generating files if an error is detected, but I don't 
see any error output coming from your test.

I'll not be able to look at this further until next week at the 
earliest. Sorry.

-- Jon



On 05/27/2010 03:48 PM, Joshua Maurice wrote:
> Silly question: is there a known bug in JavacTask.generate? I did a 
> quick google search of the bug archives, and it did not come up. It 
> seems that depending on the order of JavaFileObjects used to create 
> the JavacTask, the fifth argument to javax.tools.JavaCompiler.getTask, 
> it skips or does not skip generating files. Here's my stand alone 
> example:
>
>
> import java.io.BufferedWriter;
> import java.io.File;
> import java.io.FileWriter;
> import java.io.IOException;
> import java.io.StringWriter;
> import java.util.Arrays;
> import java.util.Iterator;
> import java.util.List;
>
> import javax.lang.model.element.Element;
> import javax.tools.DiagnosticCollector;
> import javax.tools.JavaCompiler;
> import javax.tools.JavaFileObject;
> import javax.tools.StandardJavaFileManager;
> import javax.tools.ToolProvider;
>
> import com.sun.source.tree.CompilationUnitTree;
> import com.sun.source.util.JavacTask;
>
> public class Foo {
>     public static void main(String[] args) throws IOException {
>         final File srcRoot = new File("C:/foo/src");
>         final File tgtRoot = new File("C:/foo/tgt");
>         writeToFile(new File(srcRoot + "/T3.java"), "public class T3 { 
> public static final int C = 1; }\n");
>         writeToFile(new File(srcRoot + "/T2.java"), "public class T2 
> extends T3 {}\n");
>         writeToFile(new File(srcRoot + "/T1.java"), "public class T1 
> extends T2 {}\n");
>         writeToFile(new File(srcRoot + "/Test.java"), "public class 
> Test { public static final int D = T1.C; }\n");
>
>         final List<File> sourceFiles = Arrays.asList(new File[]{
>                 new File(srcRoot, "/T2.java"),
>                 new File(srcRoot, "/T1.java"),
>                 new File(srcRoot, "/T3.java"),
>                 new File(srcRoot, "/Test.java"),
>                 });
>
>         final StringWriter compilerOutputStream = new StringWriter();
>
>         final List<String> compileOptions = Arrays.asList(new 
> String[]{"-g", "-source", "1.6", "-Xlint:unchecked", "-d", 
> tgtRoot.toString()});
>         final JavaCompiler compiler = 
> ToolProvider.getSystemJavaCompiler();
>         DiagnosticCollector<JavaFileObject> diagnosticCollector = new 
> DiagnosticCollector<JavaFileObject>();
>         final StandardJavaFileManager fileManager = 
> compiler.getStandardFileManager(diagnosticCollector, null, null);
>         final Iterable<? extends JavaFileObject> sourceFileObjects = 
> fileManager.getJavaFileObjectsFromFiles(sourceFiles);
>         System.out.println("1- javac given java source JavaFileObjects 
> " + sourceFileObjects);
>         final JavaCompiler.CompilationTask task = 
> compiler.getTask(compilerOutputStream, fileManager, null, 
> compileOptions, null, sourceFileObjects);
>         JavacTask javacTask = (JavacTask)task;
>
>         if (false) { //TOGGLE THIS
>
>             final Iterable<? extends CompilationUnitTree> parsedTrees 
> = javacTask.parse();
>             final Iterable<? extends Element> analyzedTrees = 
> javacTask.analyze();
>             final Iterable<? extends JavaFileObject> generatedFiles = 
> javacTask.generate();
>
>             System.out.println("2- " + size(parsedTrees) + " " + 
> size(analyzedTrees) + " " + size(generatedFiles));
>
>             System.out.print("3-");
>             for (JavaFileObject f : generatedFiles)
>                 System.out.print(" " + f);
>             System.out.println("");
>         } else {
>             final boolean javacCallReturn = javacTask.call();
>             System.out.println("4- " + javacCallReturn);
>         }
>
>         System.out.print("5-");
>         for (File f : tgtRoot.listFiles())
>             System.out.print(" " + f);
>         System.out.println("");
>
>         System.out.println("----");
>         System.out.println(compilerOutputStream.toString());
>     }
>
>     private static <E> int size(Iterable<E> x) {
>         int n = 0;
>         for (Iterator<E> iter = x.iterator(); iter.hasNext(); ++n)
>             iter.next();
>         return n;
>     }
>
>     private static void writeToFile(File f, String str) throws 
> IOException  {
>         f.getParentFile().mkdirs();
>         BufferedWriter fout = new BufferedWriter(new FileWriter(f));
>         try {
>             fout.write(str);
>             fout.flush();
>         } finally {
>             fout.close();
>         }
>     }
> }
>
>
> When TOGGLE THIS is true, it calls "generate" on the JavacTask. The 
> output on some execution on my computer is:
>     1- javac given java source JavaFileObjects [C:\foo\src\T2.java, 
> C:\foo\src\T1.java, C:\foo\src\T3.java, C:\foo\src\Test.java]
>     2- 4 4 2
>     3- C:\foo\tgt\T3.class C:\foo\tgt\Test.class
>     5- C:\foo\tgt\T1.class C:\foo\tgt\T2.class C:\foo\tgt\T3.class 
> C:\foo\tgt\Test.class
>     ----
>
> When TOGGLE THIS is false, it calls "call" on the JavacTask. The 
> output on some execution on my computer is:
>     1- javac given java source JavaFileObjects [C:\foo\src\T2.java, 
> C:\foo\src\T1.java, C:\foo\src\T3.java, C:\foo\src\Test.java]
>     4- true
>     5- C:\foo\tgt\T1.class C:\foo\tgt\T2.class C:\foo\tgt\T3.class 
> C:\foo\tgt\Test.class
>     ----
>
> When the order of file objects given to the JavacTask is altered, it 
> starts to work. Ex:
>         final List<File> sourceFiles = Arrays.asList(new File[]{
>                 new File(srcRoot, "/Test.java"),
>                 new File(srcRoot, "/T3.java"),
>                 new File(srcRoot, "/T2.java"),
>                 new File(srcRoot, "/T1.java"),
>                 });
> gives output:
>     1- javac given java source JavaFileObjects [C:\foo\src\Test.java, 
> C:\foo\src\T3.java, C:\foo\src\T2.java, C:\foo\src\T1.java]
>     2- 4 4 4
>     3- C:\foo\tgt\Test.class C:\foo\tgt\T3.class C:\foo\tgt\T2.class 
> C:\foo\tgt\T1.class
>     5- C:\foo\tgt\T1.class C:\foo\tgt\T2.class C:\foo\tgt\T3.class 
> C:\foo\tgt\Test.class
>     ----
>
> So, it appears as though I can work around this bug. I just have to 
> create two different JavacTasks for each "javac task" aka "pom.xml", 
> one to do the actual class file generation, done with the member 
> function "call", and a second JavacTask invocation to get the analyzed 
> parse trees to get the used types during compile (which I'm still 
> working on figuring out how to do).
>
> Finally:
>     C:\Documents and Settings\jmaurice>javac -version
>     javac 1.6.0_20




More information about the compiler-dev mailing list