JavacTask.generate bug?

Joshua Maurice joshuamaurice at gmail.com
Thu May 27 16:49:35 PDT 2010


On Thu, May 27, 2010 at 4:44 PM, Jonathan Gibbons <
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]
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://mail.openjdk.java.net/pipermail/compiler-dev/attachments/20100527/4bf022c0/attachment.html 


More information about the compiler-dev mailing list