JavacTask.generate bug?
Joshua Maurice
joshuamaurice at gmail.com
Tue Jun 15 17:52:17 PDT 2010
On Tue, Jun 15, 2010 at 3:18 PM, Jonathan Gibbons <
jonathan.gibbons at oracle.com> wrote:
>
>
> On 05/27/2010 04:56 PM, Jonathan Gibbons wrote:
>
> 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> 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
>
>
> Joshua,
>
> FWIW, I've recreated your issue using JDK 1.6, but your program works for
> me, using JDK7, using all 24 orderings of the 4 test files. So it looks
> like the bug you encountered has already been fixed in JDK 7.
>
> -- Jon
>
Excellent. Thank you. (Which of course begs the question I'm sure you've
been asked numerous times, so I'll just hint at it instead of asking
directly.)
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://mail.openjdk.java.net/pipermail/compiler-dev/attachments/20100615/4d62dbfd/attachment.html
More information about the compiler-dev
mailing list