Maven编译器插件总是将一组源检测为“陈旧”

时间:2013-07-30 10:07:39

标签: java maven build

FIXED:这是maven-compiler-plugin 3.1中的known bug

我正在将1000多个java-sources项目的基于ant的构建转换为maven。到目前为止一切都很好,但每次启动mvn compile它都会重新编译所有内容(而不是重用旧类)

使用mvn -X compile报告

[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
...

仅针对某个软件包中的文件,这可能与其他代码未引用;不是我的来源,我只是想对构建进行整理)

编译不会失败,并且正在

生成具有更新时间戳的类
/project_path/target/classes/package_path/AFile1.class
/project_path/target/classes/package_path/AFile2.class
...

然而,在查看时间戳时,java文件自昨天以来没有改变,并且类文件是最新的。为什么这些来源被确定为陈旧?我该如何调试此问题?。

即使没有发生任何更改,也必须重新编译1k +文件...


示例输出:

$ 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] ------------------------------------------------------------------------

9 个答案:

答案 0 :(得分:31)

这是maven-compiler-plugin 3.1中的一个已知问题。它在https://issues.apache.org/jira/browse/MCOMPILER-209中被跟踪(useIncrementalCompilation标志已被破坏)。

该问题与另一个3.1错误https://issues.apache.org/jira/browse/MCOMPILER-205无关(其中不生成.class输出的文件始终标记为'陈旧')。

进一步测试后,回到3.0并没有真正解决问题(它只适用于下一个mvn clean compile。但是,正如Michael Lemke在评论中建议的那样,将useIncrementalCompilation标记为false }是一个可行的替代品;现在,每次只重新编译有问题的包(而不是整个代码库)。

答案 1 :(得分:12)

Maven可能会显示如下消息:

  

[INFO]检测到更改 - 重新编译模块!

因为项目中有一个空的java文件(或所有注释掉的文件),它永远不会编译成类文件。

您可以通过使用-X运行maven来确定maven重建的原因。看看上面的消息。

答案 2 :(得分:6)

我的情况略有不同,所以我只是添加它,以防其他人有同样的问题。我的项目没有生成类,也没有package-info.java;仅.java中的src/main/java个文件。

<强> TL;博士

更新至maven-compiler-plugin 3.1或使用maven-compiler-plugin 3.0,不要在<overwrite>true</overwrite>中设置maven-resources-plugin


长版

当src树变化为零时,Maven总是显示如下输出:

$ 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

我认为这是我项目正在使用的父POM中maven-resources-plugin的配置。

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

从父POM中删除此插件,或使用<overwrite>false</overwrite>在我的项目中重新定义修复了增量构建问题。

我想知道为什么在为Maven设置<overwrite>false</overwrite>再次进行增量构建之后我必须进行两次构建,因此需要进一步调查。这只是因为第一个编译生成了一个文件(称为inputFiles.lst),用于确定已更改的文件,因此在下一次编译时,它可以使用该文件来检测更改。这由MCOMPILER-187上的a comment确认。

我意识到我正在使用maven-compiler-plugin 3.0并且可以升级到

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

这也解决了问题。 3.1使用maven-shared-incremental 1.1(而不是maven-compiler-plugin 3.0使用的1.0。请注意MCOMPILER-187MSHARED-264是覆盖此更改的2个错误。

回到maven-compiler-plugin 3.0,我观察到target/maven-status/maven-compiler-plugin/compile/default-compile/inputFiles.lst没有使用<overwrite>true</overwrite>设置生成。所以这个可能是使用maven-compiler-plugin 3.0时项目无法进行增量构建的原因。

显然,通常不希望每次编译都覆盖资源,但这里的主要问题是永远不会生成inputFiles.lst,因此Maven永远无法进行增量构建。因此检查inputFiles.lst是否存在,因为另一个插件可能导致它无法生成。

答案 3 :(得分:4)

我不明白为什么,但tucuxi答案的解决方案在我的案例中不起作用。在我的项目中,有数千个由特殊工具生成的文件,它的重新编译可能会浪费很多时间。

我尝试了以下插件配置(使用java级别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>

在第二次运行时,没有检测到过时的文件,但插件再次重新编译了所有项目。似乎默认情况下,增量编译实际上已禁用,即使指定了useIncrementalCompilation = true,仍然无法正常工作。

经过一些谷歌搜索,我只是简单地将useIncrementalCompilation参数值从“true”更改为“yes”,这对我来说很有用。

@see stackoverflow.com/a/19653164/1848640

答案 4 :(得分:1)

如果您确定没有更改,则可以传入-Dmaven.main.skip。我有一个在运行Proguard之后执行此操作的项目,因为这是重复使用Proguarded jar进行测试的唯一方法。 (注意:我在Proguard之前和之后都运行了相同的单元测试,以确保Proguard没有损坏任何东西。为了使它尽可能接近标准Maven工作流程,我在Surefire中进行了Proguard之前的运行, Proguard在故障保护中运行。)

答案 5 :(得分:0)

发生这种情况的另一种方法是,如果您的源文件位置和程序包名称不匹配。

例如如果您在src/main/java/com/example/MyClass.java中有一个源文件,但是在不匹配的com.example.util包中声明了该类:

package com.example.util;

class MyClass { ... }

编译后的类文件将以target/classes/com/example/util/MyClass.class结尾,这会混淆“陈旧文件”检查。

答案 6 :(得分:0)

我将maven编译器插件回滚到2.3.2版本,并且它仅使用Java 8编译经过修改的类,而没有问题。

答案 7 :(得分:0)

遇到同样的问题。带有mvn compile选项的Maven -X表明问题是由package-info.java文件引起的。

  

[DEBUG]检测到过时的源:... / package-info.java

问题是没有为package-info.java生成 .class 文件。

此PR中找到了解决方案:https://github.com/apache/flink/pull/5644/files 引用MCOMPILER-205

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

这意味着:

  

始终为每个package-info.java文件生成package-info.class。

答案 8 :(得分:0)

类名和文件名不匹配也会产生此错误。