I have a Java project with ~2400 classes. They are mostly generated using XJC from XML schema with a few extensions.
Compilation takes very long time, ~20 minutes, and I was wondering if there's anything I can do to improve this?
A similar project has around half the number of generated classes, but several hand-written classes instead, for a total of ~3000 classes. This compiles in a more stomachable 2-5 minutes.
I am using Java 8 (1.8.0_92 on Windows) for compilation, but using source and target version 6 (so the issue is not the slow type system on Java 8). Compilation is done using Maven 3.3.3 using maven-compiler-plugin 3.5.1. I am forking the compiler off Maven and use maxmem 2048m.
The generated classes are generally small, but I have one huge visitor touching all the generated classes (so there's a one to all and an all to one dependency). I cannot really do anything about this.
Switching from "mvn clean install" to "mvn install" (or just "mvn compile") helps, but this is not always an option (basically, Eclipse screws around with compiled files, so to be sure tests run ok, I need to clean while running tests from the command like before committing).
I don't have any background processes watching the compilation unit files (like Eclipse/SourceTree), but I do have a virus scanner (which I cannot switch off). It seems most of the time is spent by javac.
Is there something in javac that is super-linear in the number of mutually dependent classes? Or is there a way I can get around these compilation times?
E: I got a suggestion for running Maven multi-threaded; unfortunately I've already tried this, and it doesn't really help here as it's a single-module project with a lot of interdependent classes.
E2: I split the project into a module with just the JAXB code and another with the main code. Turns out, the JAXB code wasn't the culprit. I ran the Tesla Maven Profiler and it just confirmed the compilation is the issue; relevant part:
org.apache.maven.plugins:maven-compiler-plugin:3.5.1 (default-compile) 18m 48s
org.apache.maven.plugins:maven-compiler-plugin:3.5.1 (default-testCompile) 14s 770ms
org.apache.maven.plugins:maven-surefire-plugin:2.12.4 (default-test) 1m 51s
org.apache.maven.plugins:maven-war-plugin:2.0.1 (default-war) 14s 635ms
I'm perfectly fine with the duration of the last three.
This is just 1000 Java classes, all inheriting from a common visitor generated using JAXB. My compile configuration:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.5.1</version>
<configuration>
<fork>true</compiler>
<source>${compileSource}</source>
<target>${compileSource}</target>
<meminitial>512m</meminitial>
<maxmem>2048m</mexmem>
<encoding>UTF-8<eencoding>
</configuration>
</plugin>
(compileSource is 1.6)
Turns out, the issues is really in javac. Javac cannot handle classes with wildly overloaded methods very well (http://mail.openjdk.java.net/pipermail/compiler-dev/2013-May/006339.html).
I was generating a visitor, which generated a visit(...) method for each class (1100+), causing compilation of each derivative to take several seconds. As I had hundreds of these methods, this all added up.
My visitor was generated using jaxb-visitor (https://github.com/massfords/jaxb-visitor) and fixed the issue by including the typename in generated methods using my own fork of the code (https://github.com/klafbang/jaxb-visitor).
Compilation time went down (from 40 minutes) to 2 minutes.