JavacTask.generate bug?

Jonathan Gibbons jonathan.gibbons at oracle.com
Thu May 27 16:56:19 PDT 2010


On 05/27/2010 04:49 PM, Joshua Maurice wrote:
> On Thu, May 27, 2010 at 4:44 PM, Jonathan Gibbons 
> <jonathan.gibbons at oracle.com <mailto:jonathan.gibbons at oracle.com>> wrote:
>
>     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
>
>
> Using this new undocumented option, under the original code, except 
> with TOGGLE THIS to true, after cleaning out the output folder, 
> execution of the program prints:
>
> 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\T3.class C:\foo\tgt\Test.class
> ----
> [attribute T2]
> [attribute T3]
> [attribute T1]
> [attribute Test]
> [flow T2]
> [flow T3]
> [flow T1]
> [flow Test]
> [defer T2]
> [desugar T3]
> [defer T1]
> [desugar Test]
> [generate code T3]
> [generate code Test]


OK, you got my attention.  This needs to be investigated.   It looks 
significant that T1 and T2 get deferred, then not generated.

-- Jon
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://mail.openjdk.java.net/pipermail/compiler-dev/attachments/20100527/df050003/attachment.html 


More information about the compiler-dev mailing list