maven中javac编译命令错误的解决方法
我遇到了Java编译器中的一个错误,其中提交用于编译的文件的顺序可能导致代码无法编译。 我已经深入研究了代码,以找出可以重现问题的最少量代码,从而生成三个源文件 (每个1个类)。
public interface ActionSpec { public abstract int run(String param); } public enum Actions implements ActionSpec { SKIP { public int run(String d) { return 0; } }; } public class Program { public static void main(String[] args) { Actions.SKIP.run("hello"); } }
通过以特定顺序使用javac参数可以重现该问题。 简而言之,为了成功,必须始终在使用它的Program类之前编译Actions类,否则javac无法以理智的方式处理它:
# this case fails echo "Trying order: javac Program.java Actions.java ActionSpec.java" rm *class javac -verbose Program.java Actions.java ActionSpec.java # this case fails #rm *class #javac Program.java Actions.java ActionSpec.java # this case fails #rm *class #javac ActionSpec.java Program.java Actions.java # this case succeeds #rm *class #javac ActionSpec.java Actions.java Program.java # this case succeeds #rm *class #javac Actions.java ActionSpec.java Program.java # this case succeeds #rm *class #javac Actions.java Program.java ActionSpec.java
编译错误发生时始终是相同的 – 即使它们都实现了具有该run方法的接口,也无法找到Actions枚举实例上的run方法。
Program.java:6: cannot find symbol symbol : method run(java.lang.String) location: class problem.Actions Actions.SKIP.run("hello");
该漏洞似乎与甲骨文网站上报道的这个漏洞有关。 我在mac os x 10.7.2 x86_64上使用javac 1.6.0_29,但也在Linux上重现了它。
当我使用Maven构建时,这个问题变得明显,并且似乎没有对编译顺序的任何控制。 所以我正在寻找一种解决方法,要么强制maven以这样的顺序编译文件以避免这种编译器错误,要么摆弄编译器标志(或类似的东西)以避免它。 问题出现在工作站和持续集成环境中,所以它必须全面工作。 有什么建议么?
编辑:只是尝试了以下的解决方法,尽管只是将有问题的枚举分配给它实现的接口类型的变量,令人惊讶地导致错误消失。
public class Program { public static void main(String[] args) { ActionSpec a = Actions.SKIP; a.run("hello"); } }
仍对其他人的意见感兴趣。
我玩了一遍,发现添加简单的演员:
public static void main(String[] args) { ((ActionSpec)Actions.SKIP).run("hello"); }
解决了这个问题。 将此枚举作为方法参数作为接口传递也可以解决问题
这是http://bugs.sun.com/view_bug.do?bug_id=6724345中报告的错误
如果您仍在使用Java 6编译器,则建议的解决方法应该有效。 该错误已在Java 7中修复。
这是我将如何做到这一点:
- 将
ActionSpec
接口移动到另一个Maven项目。 我们通常在他们自己的项目中有接口和公共域类,例如foo-service-specs
。 - 将其他类保留在实现项目中,例如
foo-service-impl
。 - 在
foo-service-impl
包含foo-service-specs
项目作为依赖foo-service-impl
。
通过这样做,您可以确保编译顺序正常工作,并且它也适用于持续集成。
尝试多次执行编译器插件。 使用default-compile
作为第一个执行ID,将新配置添加到Maven的默认编译器执行中。 使用默认执行中的
config元素首先编译枚举。 对于第二次执行,您将使用
和
,其中
将是您的所有代码,并且排除将是已编译的枚举。
我认为这适用于您的示例程序,但我没有测试它。 我之前用Maven 3测试了类似的东西,它运行良好。
org.apache.maven.plugins maven-compiler-plugin 2.3.2 1.6 1.6 default-compile compile **/Actions.* second compile **/* **/Actions.*
我们遇到了同样的问题。 多个maven compiler
插件的执行对我们maven compiler
…