JDK-6966604 : JavacFiler not correctly notified of lastRound
  • Type: Bug
  • Component: tools
  • Sub-Component: javac
  • Affected Version: 7
  • Priority: P3
  • Status: Closed
  • Resolution: Fixed
  • OS: generic
  • CPU: generic
  • Submitted: 2010-07-04
  • Updated: 2012-05-21
  • Resolved: 2011-03-07
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
JDK 7
7 b105Fixed
Related Reports
Relates :  
Relates :  
Relates :  
Relates :  
Description
The following lines from JavacProcessingEnvironment show that the processors for the last round are run *before* setting the lastRound status of the JavacFiler:


        roots = runLastRound(xout, roundNumber, errorStatus, compiler, roots, taskListener);
        // Set error status for any files compiled and generated in
        // the last round
        if (log.unrecoverableError)
            errorStatus = true;

        compiler.close(false);
        currentContext = contextForNextRound(currentContext, true);
        compiler = JavaCompiler.instance(currentContext);




This is verified by the following trace output:


[parsing started RegularFileObject[./examples/ProcFileCreateLastRound/ProcFileCreateLastRound.java]]
[parsing completed 24ms]
[search path for source files: dist/Examples.jar]
[search path for class files: langtools/dist/lib/javac.jar,langtools/dist/lib/javap.jar,/w/opt/jdk/jdk1.7.0-b99-amd64/jre/lib/resources.jar,/w/opt/jdk/jdk1.7.0-b99-amd64/jre/lib/rt.jar,/w/opt/jdk/jdk1.7.0-b99-amd64/jre/lib/sunrsasign.jar,/w/opt/jdk/jdk1.7.0-b99-amd64/jre/lib/jsse.jar,/w/opt/jdk/jdk1.7.0-b99-amd64/jre/lib/jce.jar,/w/opt/jdk/jdk1.7.0-b99-amd64/jre/lib/charsets.jar,/w/opt/jdk/jdk1.7.0-b99-amd64/jre/classes,/w/opt/jdk/jdk1.7.0-b99-amd64/jre/lib/ext/localedata.jar,/w/opt/jdk/jdk1.7.0-b99-amd64/jre/lib/ext/sunec.jar,/w/opt/jdk/jdk1.7.0-b99-amd64/jre/lib/ext/sunpkcs11.jar,/w/opt/jdk/jdk1.7.0-b99-amd64/jre/lib/ext/sunjce_provider.jar,/w/opt/jdk/jdk1.7.0-b99-amd64/jre/lib/ext/dnsns.jar,dist/Examples.jar]
[loading ZipFileIndexFileObject[/w/opt/jdk/jdk1.7.0-b99-amd64/lib/ct.sym(META-INF/sym/rt.jar/java/lang/Object.class)]]
Round 1:
        input files: {ProcFileCreateLastRound}
        annotations: []
        last round: false
AnnoProc: pOver:false
Processor AnnoProc matches [] and returns false.
JavacProcessingEnvironment.runLastRound
Round 2:
        input files: {}
        annotations: []
        last round: true ********************************************************************************************
AnnoProc: pOver:true
JavacFiler.createSourceOrClassFile lastRound:false name:Gen lint:true ***********************************************
[parsing started RegularFileObject[classes/Gen.java]]
[parsing completed 0ms]
JavacFiler.newRound: lastRound:true *********************************************************************************
java.lang.Exception: Stack trace
        at java.lang.Thread.dumpStack(Thread.java:1353)
        at com.sun.tools.javac.processing.JavacFiler.newRound(JavacFiler.java:540)
        at com.sun.tools.javac.processing.JavacProcessingEnvironment.doProcessing(JavacProcessingEnvironment.java:921)
        at com.sun.tools.javac.main.JavaCompiler.processAnnotations(JavaCompiler.java:1061)
        at com.sun.tools.javac.main.JavaCompiler.compile(JavaCompiler.java:796)
        at com.sun.tools.javac.main.Main.compile(Main.java:409)
        at com.sun.tools.javac.api.JavacTaskImpl.call(JavacTaskImpl.java:139)
        at Example.compile_jsr199(Example.java:191)
        at Example.run(Example.java:158)
        at Example.run(Example.java:120)
        at RunExamples.run(RunExamples.java:74)
        at RunExamples.main(RunExamples.java:14)
JavacProcessingEnvironment.updateProcessingState: lastRound:true
JavacFiler.newRound: lastRound:true
java.lang.Exception: Stack trace
        at java.lang.Thread.dumpStack(Thread.java:1353)
        at com.sun.tools.javac.processing.JavacFiler.newRound(JavacFiler.java:540)
        at com.sun.tools.javac.processing.JavacProcessingEnvironment.updateProcessingState(JavacProcessingEnvironment.java:1024)
        at com.sun.tools.javac.processing.JavacProcessingEnvironment.doProcessing(JavacProcessingEnvironment.java:955)
        at com.sun.tools.javac.main.JavaCompiler.processAnnotations(JavaCompiler.java:1061)
        at com.sun.tools.javac.main.JavaCompiler.compile(JavaCompiler.java:796)
        at com.sun.tools.javac.main.Main.compile(Main.java:409)
        at com.sun.tools.javac.api.JavacTaskImpl.call(JavacTaskImpl.java:139)
        at Example.compile_jsr199(Example.java:191)
        at Example.run(Example.java:158)
        at Example.run(Example.java:120)
        at RunExamples.run(RunExamples.java:74)
        at RunExamples.main(RunExamples.java:14)
[search path for source files: dist/Examples.jar]
[search path for class files: langtools/dist/lib/javac.jar,langtools/dist/lib/javap.jar,/w/opt/jdk/jdk1.7.0-b99-amd64/jre/lib/resources.jar,/w/opt/jdk/jdk1.7.0-b99-amd64/jre/lib/rt.jar,/w/opt/jdk/jdk1.7.0-b99-amd64/jre/lib/sunrsasign.jar,/w/opt/jdk/jdk1.7.0-b99-amd64/jre/lib/jsse.jar,/w/opt/jdk/jdk1.7.0-b99-amd64/jre/lib/jce.jar,/w/opt/jdk/jdk1.7.0-b99-amd64/jre/lib/charsets.jar,/w/opt/jdk/jdk1.7.0-b99-amd64/jre/classes,/w/opt/jdk/jdk1.7.0-b99-amd64/jre/lib/ext/localedata.jar,/w/opt/jdk/jdk1.7.0-b99-amd64/jre/lib/ext/sunec.jar,/w/opt/jdk/jdk1.7.0-b99-amd64/jre/lib/ext/sunpkcs11.jar,/w/opt/jdk/jdk1.7.0-b99-amd64/jre/lib/ext/sunjce_provider.jar,/w/opt/jdk/jdk1.7.0-b99-amd64/jre/lib/ext/dnsns.jar,dist/Examples.jar]
[loading ZipFileIndexFileObject[/w/opt/jdk/jdk1.7.0-b99-amd64/lib/ct.sym(META-INF/sym/rt.jar/java/lang/Object.class)]]
[checking ProcFileCreateLastRound]
[wrote RegularFileObject[classes/ProcFileCreateLastRound.class]]
[checking Gen]
[wrote RegularFileObject[classes/Gen.class]]
[total 232ms]

        filer.newRound(currentContext, true);

Comments
EVALUATION Added example back. Refactored code by introducing new Round object contain state and methods for a round of processing.
30-07-2010

EVALUATION This bug is blocking 6968063 (test/tools/javac/diags/examples) so for now, I've removed the example that displays this problem and added the example as an attachment here, for use when this bug is fixed.
21-07-2010

EVALUATION updateProcessingState(currentContext, true); is currently called for the final *compilation*, not the last round of annotation processing, which is the penultimate compilation. Also note that these lines starting round about line 953 look potentially gratuitous (but not invalid): } else { // Final compilation compiler.close(false); currentContext = contextForNextRound(currentContext, true); this.context = currentContext; updateProcessingState(currentContext, true); compiler = JavaCompiler.instance(currentContext); There is no need to close the compiler and create a new context because a new compiler and fresh context were unconditionally created round about line 918, after calling runLastRound.
04-07-2010

EVALUATION updateProcessingState is currently called in line 905 after the context has been created for the next round. The problem is that this is before it is known if this is the last round or not, leading to the observed error. The minimal fix would be to fix up the filer by resetting it with a repeated call to filer.newRound(currentContext, true); before roots = runLastRound(xout, roundNumber, errorStatus, compiler, roots, taskListener); Arguably, a better fix is to re-examine when updateProcessingState is called so that it is called before processors are invoked (when the lastRound status is known) instead of after updating the context (when the lastRound status has not yet been determined.)
04-07-2010

EVALUATION When fixing this, it would be good to remove the following nearby line declaring an unused variable: line 873: JavaFileManager fileManager = currentContext.get(JavaFileManager.class); Also, minor grammatical errors in the following comment at line 854 /* * Processors for round n have run to completion. Prepare * for round (n+1) by checked for errors raised by * annotation processors and then checking for syntax * errors on any generated source files. */
04-07-2010