Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Maven/Gradle List out the Compiled Classes

Maven and Gradle both uses incremental build by default if I am not mistaken.

  • For fresh/first build, It would build all class files.
  • Upon next build without any change, it doesn't build any class files.
  • If I modify the A.java, it would recompile the module.

Is there any option to get the list of class files that are compiled in this build?

like image 380
RaceBase Avatar asked Dec 15 '15 05:12

RaceBase


1 Answers

How about maven.compiler.verbose property?

If I set it to true I get either

% mvn compile -Dmaven.compiler.verbose=true 2>&1 | grep class
[INFO] Nothing to compile - all classes are up to date

or if I modify the A.java file

% mvn compile -Dmaven.compiler.verbose=true 2>&1 | grep class | grep wrote
[wrote RegularFileObject[/tmp/mvn-compile/target/classes/A.class]]
[wrote RegularFileObject[/tmp/mvn-compile/target/classes/B.class]]

... and other similar output

You can also get little bit deeper into your OS and trace (e.g., strace on some Linux distros) write syscalls (posix compliant platforms) and grep the .class files that are being written.

You can also use option -Dmaven.compiler.fork=true which forks javac (which used to be a default but is not anymore apparently). You can trace the arguments of javac, which are passed through a temporary file (which exists only during the execution of javac, for instance it is /tmp/org.codehaus.plexus.compiler.javac.JavacCompiler2179201625419771061arguments). You can also cat this file and see which files are passed to javac to be recompiled. In my case (Mac OS X), this file is stored in /tmp and to output it, I naively run

% cd /tmp; while true; do ls org.codehaus.plexus.compiler.javac.JavacCompiler* | xargs cat; sleep 1; done
zsh: no matches found: org.codehaus.plexus.compiler.javac.JavacCompiler*
zsh: no matches found: org.codehaus.plexus.compiler.javac.JavacCompiler*
zsh: no matches found: org.codehaus.plexus.compiler.javac.JavacCompiler*
"-d"
"/tmp/mvn-compile/target/classes"
"-classpath"
"/Users/stepan/.m2/repository/com/typesafe/config/1.3.0/config-1.3.0.jar:/Users/stepan/.m2/repository/com/fasterxml/jackson/core/jackson-core/2.6.4/jackson-core-2.6.4.jar:"
"-sourcepath"
"/tmp/mvn-compile/src/main/java/A.java"
"/tmp/mvn-compile/src/main/java/B.java"
"-s"
"/tmp/mvn-compile/target/generated-sources/annotations"
"-g"
"-verbose"
"-nowarn"
"-target"
"1.8"
"-source"
"1.8"
"-encoding"
"UTF-8"

Another question is how Maven decides which class to recompile. If I remember it correctly, it used to be based on a comparison of timestamps of .java files vs their .class matching files. If .java file was newer, then it was added to javac to be recompiled. However, I can see right now, it's much more complicated and to understand the reasons, I would recommend debug maven execution and look at AbstractCompilerMojo.java and its execute method.
For instance, if there is package-info.java file in my sources directory, all the classes are always recompiled even if they are not changed.

like image 122
Stepan Vavra Avatar answered Sep 18 '22 16:09

Stepan Vavra