【问题标题】:Maven compiler plugin always detecting a set of sources as "stale"Maven 编译器插件总是将一组源检测为“陈旧”
【发布时间】:2013-07-30 10:15:59
【问题描述】:

已修复:这是 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
...

仅适用于某个包中的文件,其余代码可能未引用该文件;不是我的来源,我只是想对构建进行 mavenize)

编译没有失败,并且正在生成具有更新时间戳的类

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

【问题讨论】:

标签: java maven build


【解决方案1】:

这是 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 在 cmets 中建议的那样,将 useIncrementalCompilation 标记为 false 是一个可行的替代方案;现在,每次只重新编译有问题的包(而不是整个代码库)。

【讨论】:

  • 我看到了同样的问题。不过,在我的情况下,使用 3.0 并没有帮助。我只是继续使用 3.1 并将 useIncrementalCompilation 设置为 false。为我修复它。我实际上正在使用替换插件修改单个 Java 文件,这会导致这种不幸的行为。
  • 如果您将您的评论改写为答案,我将接受它作为正确答案。备份到 3.0 只在下一次完整的 mvn clean compile...
  • 嗨,我们究竟如何进入并将“useIncrementalCompilation”更改为false?它存在于什么文件中?谢谢!
  • @mattman88 这可以在 pom.xml 文件中设置: org.apache.maven.pluginsmaven-compiler -plugin3.2false
  • 实际上根据这两个问题的最后评论,它并没有被破坏,但是人们认为该设置应该做什么是错误的。实际上,你应该使用 true 并避免在那里使用 false
【解决方案2】:

Maven 可能会显示如下消息:

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

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

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

【讨论】:

  • 我在使用 v3.7.0 时遇到了同样的问题。这是最好的答案。如果您运行mvn -X,您将看到:[DEBUG] useIncrementalCompilation enabled 后跟... [DEBUG] Stale source detected: ${filePath},它是我项目中的 2 个空源文件。太棒了!
  • 感谢您的提示。删除已被评论超过两年的文件(不知道为什么它们仍然存在),我设法将编译时间减少了 50% 以上。
  • -X 找到了问题...我添加了一个 package-info.java,只有 cmets 来描述包,它显示为陈旧。太糟糕了!
  • 它将 package-info.java 视为空(仅包含 javadoc)。
【解决方案3】:

面临同样的问题。 Maven mvn compile-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。

【讨论】:

【解决方案4】:

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

tl;dr

更新到maven-compiler-plugin 3.1 或使用maven-compiler-plugin 3.0 并且不要在maven-resources-plugin 中设置&lt;overwrite&gt;true&lt;/overwrite&gt;


加长版

在 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 中删除此插件,或在我的项目中使用 &lt;overwrite&gt;false&lt;/overwrite&gt; 重新定义修复了增量构建问题。

我想知道为什么在设置 &lt;overwrite&gt;false&lt;/overwrite&gt; 之后我必须进行两次构建,以便 Maven 再次进行增量构建,因此进一步调查。这仅仅是因为第一次编译生成了一个文件(称为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 不是用 &lt;overwrite&gt;true&lt;/overwrite&gt; 设置生成的。因此,这可能是项目在使用 maven-compiler-plugin 3.0 时无法进行增量构建的原因。

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

【讨论】:

    【解决方案5】:

    我不明白为什么,但是来自 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”,这对我有用。

    @另见stackoverflow.com/a/19653164/1848640

    【讨论】:

    • "yes"这里和"false"一样,如:not "true"
    • 他的意思是使用 false 在你链接的问题中,任何不是“真”的东西都是“假”,这就是为什么“是”给了你“假”的效果。
    【解决方案6】:

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

    【讨论】:

    • 感谢您提供更新的答案 - Maven 3.5 2018/08/20
    【解决方案7】:

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

    【讨论】:

      【解决方案8】:

      另一种可能发生的情况是源文件位置和包名称不匹配。

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

      package com.example.util;
      
      class MyClass { ... }
      

      编译后的类文件将在target/classes/com/example/util/MyClass.class 结束,这会混淆'stale file'检查。

      【讨论】:

        【解决方案9】:

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

        【讨论】:

          猜你喜欢
          • 2021-01-03
          • 1970-01-01
          • 2017-03-18
          • 2016-08-10
          • 2013-03-07
          • 2011-12-18
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多