javac: ending positions generation and DiagnosticListener

Jonathan Gibbons jonathan.gibbons at
Fri Dec 6 09:30:40 PST 2013

On 12/06/2013 09:08 AM, Eugene Zhuravlev wrote:
> Hi,
> 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,

This is done deliberately, since there is no way to tell if a client of 
the Compiler API needs the information or not.

-- Jon

More information about the compiler-dev mailing list