javac: ending positions generation and DiagnosticListener

Eugene Zhuravlev jeka at
Fri Dec 6 09:08:56 PST 2013


My question is about the strange behavior javac exhibits when invoked 
via Compiler API. In the latest versions of IntelliJ IDEA we are using 
Compiler API for javac invocation. After switching to this approach 
we've received a number of complaints from our users about javac's high 
memory usage. Large projects requiring compilation of big number of 
large files in one go are especially affected. Surprisingly compilation 
of the same project using the same JDK, but with ant script requires 
less heap memory for javac.
After digging into javac's sources I found the reason: extra memory is 
needed for the "end positions" data gathered by the compiler.
Whether this option is on is controlled by the flag "genEndPos" in class.
The flag is initialized in constructor like this:

         genEndPos     = options.isSet(XJCOV) ||
                         context.get(DiagnosticListener.class) != null;

So a mere presence of a DiagnosticListener makes compiler store end 
positions and probably related stuff. As we use Compiler API, we add 
this listener and thus this data is always generated, even if not used.

The question is: is this done deliberately, or this is just a "legacy 
code" that can be corrected? Javac's excessive memory usage can 
dramatically affect performance when compiling large projects, so 
removing the check "context.get(DiagnosticListener.class) != null" would 
be a good optimization.
Currently we can only advice our users to increase maximum heap size for 
the build process, as there is no way to switch this flag off.

Thanks in advance for any information,

Best regards,

Eugene Zhuravlev
Software Developer
"Develop with pleasure!"

More information about the compiler-dev mailing list