Maven compiler plugin always detecting a set of sources as "stale"
Asked Answered
P

10

77

FIXED: this is a known bug in maven-compiler-plugin 3.1

I am converting an ant-based build of a 1000+ java-sources project to maven. So far so good, but every time launch mvn compile it recompiles everything (instead of reusing old classes)

Using mvn -X compile reports that

[DEBUG] Stale source detected: /project_path/src/main/java/package_path/AFile1.java
[DEBUG] Stale source detected: /project_path/src/main/java/package_path/AFile2.java
...

(only for files in a certain package, which is possibly unreferenced from the rest of the code; not my sources, I am just trying to mavenize the build)

Compilation does not fail, and classes with updated timestamps are being generated at

/project_path/target/classes/package_path/AFile1.class
/project_path/target/classes/package_path/AFile2.class
...

However, when looking at timestamps, the java files have not changed since yesterday, and the class files are current. Why are these sources determined to be stale? How can I debug this issue?.

It is a drag to have to recompile 1k+ files even when no changes have occurred...


Sample output:

$ mvn clean compile
[INFO] Scanning for projects...
[INFO]                                                                         
[INFO] ------------------------------------------------------------------------
[INFO] Building MyProject 1.9.0-SNAPSHOT
[INFO] ------------------------------------------------------------------------
[WARNING] The POM for net.sourceforge:jffmpeg:jar:1.1.0 is missing, no dependency information available
[INFO] 
[INFO] --- maven-clean-plugin:2.4.1:clean (default-clean) @ my-project ---
[INFO] Deleting /project_path/target
[INFO] 
[INFO] --- maven-resources-plugin:2.5:resources (default-resources) @ my-project ---
[debug] execute contextualize
[INFO] Using 'UTF-8' encoding to copy filtered resources.
[INFO] skip non existing resourceDirectory /project_path/src/main/resources
[INFO] 
[INFO] --- maven-compiler-plugin:3.1:compile (default-compile) @ my-project ---
[INFO] Changes detected - recompiling the module!
[INFO] Compiling 1162 source files to project_path/target/classes
....
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 11.215s
[INFO] Finished at: Tue Jul 30 12:42:25 CEST 2013
[INFO] Final Memory: 25M/429M
[INFO] ------------------------------------------------------------------------



$ mvn compile
[INFO] Scanning for projects...
[INFO]                                                                         
[INFO] ------------------------------------------------------------------------
[INFO] Building MyProject 1.9.0-SNAPSHOT
[INFO] ------------------------------------------------------------------------
[WARNING] The POM for net.sourceforge:jffmpeg:jar:1.1.0 is missing, no dependency information available
[INFO] 
[INFO] --- maven-resources-plugin:2.5:resources (default-resources) @ my-project ---
[debug] execute contextualize
[INFO] Using 'UTF-8' encoding to copy filtered resources.
[INFO] skip non existing resourceDirectory /project_path/src/main/resources
[INFO] 
[INFO] --- maven-compiler-plugin:3.1:compile (default-compile) @ my-project ---
[INFO] Changes detected - recompiling the module!
[INFO] Compiling 1162 source files to /project_path/target/classes
... 
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 12.140s
[INFO] Finished at: Tue Jul 30 12:42:44 CEST 2013
[INFO] Final Memory: 22M/379M
[INFO] ------------------------------------------------------------------------
Paranoiac answered 30/7, 2013 at 10:7 Comment(5)
Providing you don't do a mvn clean compile Maven will only compile the source files that have changed; see - #11773247Deeannadeeanne
That is what I thought. However, it is not what I get...Paranoiac
@tucuxi: Add an answer :)Kiyohara
pom.xml - look in the maven-compiler- plugin sectionParanoiac
This is the good answer: #16963512Krohn
P
42

This is a known problem in maven-compiler-plugin 3.1. It is being tracked in https://issues.apache.org/jira/browse/MCOMPILER-209 (the useIncrementalCompilation flag is broken).

The problem is unrelated to another 3.1 bug, https://issues.apache.org/jira/browse/MCOMPILER-205 (where files that do not produce .class outputs are always flagged as 'stale').

After testing further, going back to 3.0 did not actually fix the problem (it only works until the next mvn clean compile. However, as Michael Lemke suggests in comments, marking useIncrementalCompilation to false is a workable substitute; now, only the offending package gets recompiled each time (instead of the whole code-base).

Paranoiac answered 30/7, 2013 at 13:12 Comment(5)
I am seeing the same kind of problem. Using 3.0 doesn't help in my case, though. I just keep using 3.1 and set useIncrementalCompilation to false. Fixes it for me. I am actually modifying a single Java file with the replacer plugin which causes this unfortunate behavior.Gauvin
If you rewrite your comment as an answer, I will accept it as the correct answer. Backing up to 3.0 only worked until the next full mvn clean compile...Paranoiac
Hi, how exactly do we go in and change "useIncrementalCompilation" to false? What file does that live in? Thanks!Grobe
@Grobe This can be set in the pom.xml file: <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>3.2</version> <configuration> <useIncrementalCompilation>false</useIncrementalCompilation> </configuration> </plugin> </plugins> </build>Nathanialnathaniel
Actually according to the last comment at both those issues, it is not broken, but people perceive wrong on what that setting is supposed to do. Actually, you should use true and avoid using false thereBalsa
M
48

Maven may show a message like:

[INFO] Changes detected - recompiling the module!

Because you have an empty java file (or all commented out) in the project that never compiles into a class file.

You can identify the reason why maven rebuilds by running maven with -X. Look near the above message.

Motherinlaw answered 18/10, 2017 at 1:46 Comment(5)
I was experiencing same issue with v3.7.0. This is the best answer. If you run mvn -X you will see: [DEBUG] useIncrementalCompilation enabled followed by ... [DEBUG] Stale source detected: ${filePath} and it was 2x empty source files in my project. BRILLIANT!Bounds
Thanks for the tip. Removing files that have been commented for more than two years (no idea why they were still there in the first place), I managed reduce compilation time with more than 50%.Inhere
The -X find the issue... I added a package-info.java with only comments to describe the package and it shows as stale. Too bad!Amado
it is treating package-info.java as empty (which only contains javadoc).Tussore
In my case, the -X option help me understand that it is a generated file by antlr3, need to understand why it gets regenerated every time.Cataplasia
P
42

This is a known problem in maven-compiler-plugin 3.1. It is being tracked in https://issues.apache.org/jira/browse/MCOMPILER-209 (the useIncrementalCompilation flag is broken).

The problem is unrelated to another 3.1 bug, https://issues.apache.org/jira/browse/MCOMPILER-205 (where files that do not produce .class outputs are always flagged as 'stale').

After testing further, going back to 3.0 did not actually fix the problem (it only works until the next mvn clean compile. However, as Michael Lemke suggests in comments, marking useIncrementalCompilation to false is a workable substitute; now, only the offending package gets recompiled each time (instead of the whole code-base).

Paranoiac answered 30/7, 2013 at 13:12 Comment(5)
I am seeing the same kind of problem. Using 3.0 doesn't help in my case, though. I just keep using 3.1 and set useIncrementalCompilation to false. Fixes it for me. I am actually modifying a single Java file with the replacer plugin which causes this unfortunate behavior.Gauvin
If you rewrite your comment as an answer, I will accept it as the correct answer. Backing up to 3.0 only worked until the next full mvn clean compile...Paranoiac
Hi, how exactly do we go in and change "useIncrementalCompilation" to false? What file does that live in? Thanks!Grobe
@Grobe This can be set in the pom.xml file: <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>3.2</version> <configuration> <useIncrementalCompilation>false</useIncrementalCompilation> </configuration> </plugin> </plugins> </build>Nathanialnathaniel
Actually according to the last comment at both those issues, it is not broken, but people perceive wrong on what that setting is supposed to do. Actually, you should use true and avoid using false thereBalsa
M
19

Faced the same problem. Maven mvn compile with -X option showed that the problem is caused by package-info.java file.

[DEBUG] Stale source detected: .../package-info.java

The problem is that there is no .class file generated for package-info.java.

The solution was found in this PR: https://github.com/apache/flink/pull/5644/files referencing MCOMPILER-205

<compilerArgs>
    <arg>-Xpkginfo:always</arg>
</compilerArgs>

which means:

Always generate package-info.class for every package-info.java file.

Mute answered 12/7, 2019 at 9:41 Comment(2)
javadoc.io/static/io.earcam.wrapped/jdk.compiler/1.8.132/com/… This option may be useful in conjunction with build systems (such as Ant) that expect javac to generate at least one .class file for every .java file.Mcgrath
Note that the package-info.java file must not be empty to result into a package-info.class fileMcgrath
O
9

My situation was slightly different, so I'm just adding this in case someone else has the same issue. My project has no generated classes and no package-info.java; only .java files in src/main/java.

tl;dr

Update to maven-compiler-plugin 3.1 or use maven-compiler-plugin 3.0 and do not set <overwrite>true</overwrite> in maven-resources-plugin.


Long version

With zero src tree changes, Maven was always showing output like:

$ mvn -o compile

[INFO] --- maven-compiler-plugin:3.0:compile (default-compile) @ my-project ---
[INFO] Changes detected - recompiling the module!
[INFO] Compiling 134 source files to /home/me/my/project/target/classes

I thought it was the configuration of the maven-resources-plugin in a parent POM my project is using.

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-resources-plugin</artifactId>
    <configuration>
        <overwrite>true</overwrite>
    </configuration>
</plugin>

Removing this plugin from the parent POM, or redefining in my project with <overwrite>false</overwrite> fixed the incremental build problem.

I wondered why I had to do two builds after setting <overwrite>false</overwrite> for Maven to do incremental builds again, so investigated further. That is simply because the first compile generates a file (called inputFiles.lst) that is used to determine the files that have changed, so on the next compile it can use that file to detect changes. This is confirmed by a comment on MCOMPILER-187.

I realised I was using maven-compiler-plugin 3.0 and could just upgrade to

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-compiler-plugin</artifactId>
    <version>3.1</version>
</plugin>

which also fixed the problem. 3.1 uses maven-shared-incremental 1.1 (instead of 1.0 which maven-compiler-plugin 3.0 uses. Note that MCOMPILER-187 and MSHARED-264 are the 2 bugs covering the change.

So back with maven-compiler-plugin 3.0, I observed that the target/maven-status/maven-compiler-plugin/compile/default-compile/inputFiles.lst was not being generated with <overwrite>true</overwrite> set. So this could be a reason why a project fails to have incremental builds when using maven-compiler-plugin 3.0.

Clearly, overwriting the resources every compile is not usually desired, but the main problem here is that inputFiles.lst is never generated, so Maven will never be able to make an incremental build. So check for the existence of inputFiles.lst as maybe another plugin has somehow caused it to not be generated.

Outlawry answered 26/3, 2014 at 15:47 Comment(0)
T
4

I don't understand why, but the solution from tucuxi's answer doesn't work in my case. In my project there are thousands of files generated by special tool and its recompilation may waste really a lot of time.

I've tried the following plugin configuration (with java level 1.5):

<plugin>
    <artifactId>maven-compiler-plugin</artifactId>
    <version>3.1</version>
    <configuration>
        <source>1.5</source>
        <target>1.5</target>
        <useIncrementalCompilation>true</useIncrementalCompilation>
    </configuration>
</plugin>

On a second run, there are no stale files was detected but the plugin recompiled all the project again. It seems that incremental compilation actually disabled by default, and still not working even if useIncrementalCompilation=true specified.

After some googling, I've simply changed useIncrementalCompilation parameter value from "true" to "yes" and this do the trick for me.

@see also https://mcmap.net/q/266528/-maven-compiler-recompile-all-files-instead-modified

Terryl answered 21/3, 2014 at 13:20 Comment(2)
"yes" here is the same as "false", as in: not "true"Bertina
He meant use <useIncrementalCompilation>false</useIncrementalCompilation> In the question you linked, any thing not "true" is "false", that's why "yes" gave you the "false" effect.Empennage
S
3

If you're sure there's been no change, you can pass in -Dmaven.main.skip. I have a project where I do this after running Proguard, since it's the only way to reuse the Proguarded jar for tests. (NB: I run the same unit tests before Proguard as after, to make sure Proguard hasn't broken anything. To bring this as close to the standard Maven workflow as possible, I do the pre-Proguard run in Surefire and the post-Proguard run in Failsafe.)

Solus answered 22/7, 2018 at 4:21 Comment(1)
Thank you for an updated answer - Maven 3.5 2018/08/20Iridissa
S
2

This is a very edge case I had and was extremely hard to figure out.

In my project all test files in a certain package were recompiled every time although there were no changes.

Turns out that one of the folders was named com.example instead of just com with a subdir example. The IDE does not show this as it combines it to com.example so it was not obvious.

I had to debug the maven compiler plugin to find this out. The generated test classes were in a correct directory structure but the compiler plugin was looking for the class files in a com.example directory, which did not exist. And so all test files were marked as stale.

Solution was to rename the directory from com.example to com and create a new subdir example in it.

Stannwood answered 15/7, 2022 at 21:36 Comment(0)
D
1

Another way this can happen is if your source file location and package name are mismatched.

e.g. if you have a source file in src/main/java/com/example/MyClass.java but the class is declared in a mismatched com.example.util package:

package com.example.util;

class MyClass { ... }

The compiled class file will end up in target/classes/com/example/util/MyClass.class and this will confuse the 'stale file' check.

Dooley answered 26/10, 2018 at 14:16 Comment(0)
Z
1

Mismatch of classname and filename also produce this error.

Zoophyte answered 15/7, 2020 at 17:19 Comment(0)
F
0

I rolled back maven compiler plugin to version 2.3.2 and it compiles only modified classes with java 8 without problems.

Faradmeter answered 21/1, 2019 at 18:50 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.