--- 剧透警告 ---
简短的回答是,为了将源代码编译为旧版本,您需要同时提供-source
选项和-bootclasspath
. 见这篇文章。如果你想把源码编译成更新的版本,你需要在编译器插件上设置, <source>
, <target>
, <compilerVersion>
, <fork>
, 并在surefire插件上设置...<executable>
<jvm>
现在的故事...
我遇到了同样的问题。事实证明,编译以前的版本可能不像设置<source>
和<target>
. 我的具体情况是我有一个 Java 1.7 JDK,而我的类与 1.7 不兼容(他们向我正在实现的接口添加了一个新方法)。当我尝试编译它时,编译器给了我一条错误消息,指出我没有实现接口方法。无论如何,我尝试设置编译器插件:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.3.2</version>
<configuration>
<source>1.6</source>
<target>1.6</target>
<encoding>UTF-8</encoding>
</configuration>
</plugin>
但是当我运行构建时,我得到了同样的错误。所以我在调试中运行了 maven 并看到了这个:
[INFO] [DEBUG] Command line options:
[INFO] [DEBUG] -d C:\... -nowarn -target 1.6 -source 1.6 -encoding UTF-8
请注意,为简洁起见,将 ... 代替实际参数
在输出中。开头的消息-d
是实际的完整编译参数列表。因此,如果您删除该-nowarn
标志并将其余部分粘贴到javac
命令行之后,您可以看到编译器的实际输出:
javac -d C:\... -target 1.6 -source 1.6 -encoding UTF-8
warning: [options] bootstrap class path not set in conjunction with -source 1.6
这会打印出未与 -source 1.6 一起设置的方便的警告引导类路径。在谷歌上搜索一下就会出现这篇文章,其中指出:
要使用 JDK N 中的 javac 交叉编译到旧平台版本,正确的做法是:
- 使用较旧的 -source 设置。
- 将引导类路径设置为针对旧平台的 rt.jar(或等效文件)进行编译。
如果不采取第二步,javac 将尽职尽责地使用旧语言规则与新库相结合,这可能导致类文件在旧平台上不起作用,因为可能包含对不存在的方法的引用。
现在参考编译器插件的 Maven 文档给出:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.5.1</version>
<configuration>
<compilerArguments>
<verbose />
<bootclasspath>${java.home}\lib\rt.jar</bootclasspath>
</compilerArguments>
</configuration>
</plugin>
然后,您可以将其与之前的配置相结合以获得:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.3.2</version>
<configuration>
<source>1.6</source>
<target>1.6</target>
<encoding>UTF-8</encoding>
<bootclasspath>${java.home}\lib\rt.jar</bootclasspath>
</configuration>
</plugin>
现在您只需要使${java.home}
变量对您的 mvn 可用(通过 -D 系统属性,或通过普通的旧环境变量,或者您可以非常花哨并将其填充到用户设置中的 java 6 配置文件中)。
现在只需运行你的构建并在它突然消失的时候去喝一杯冰镇啤酒......
- - 编辑 - -
最后一件事...在您的引导类路径中包含 rt.jar始终是必需的,但是,我发现根据具体情况可能需要更多。我必须包含 jce.jar(与 rt.jar 在同一目录中),因为我的应用程序正在进行加密工作。
---- 编辑 2 ----
为了笑容,我尝试了另一个方向。我没有使用为 java 6 编译的 java 7 运行 maven,而是使用为 java 7 编译的 java 6 运行 maven。第一次尝试非常简单:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.5.1</version>
<configuration>
<source>1.7</source>
<target>1.7</target>
<fork>true</fork>
<verbose>true</verbose>
<compilerVersion>1.7</compilerVersion>
<executable>${JAVA_7_HOME}/bin/javac</executable>
<encoding>UTF-8</encoding>
</configuration>
</plugin>
基本上,我将我的<source>
and设置<target>
为 1.7,但这显然还不够,因为 6 无法编译 7 代码。所以回到编译器插件,实际上有一个示例页面描述了需要做什么。也就是说,您需要<fork>
使用 java 7 关闭一个新进程<executable>
。所以现在我想我已经准备好了。是时候启动构建了...
C:\Projects\my-project>mvn package
...
Caused by: java.lang.UnsupportedClassVersionError: mypackage.StupidTest : Unsup
ported major.minor version 51.0
...
[INFO] ------------------------------------------------------------------------
[INFO] BUILD FAILURE
[INFO] ------------------------------------------------------------------------
UnsupportedClassVersionError 到底是什么?仔细观察会告诉我们它是失败的 maven-surefire-plugin。所以我尝试了一下mvn compile
,果然我得到了成功,因为surefire插件从未启动过。所以我运行mvn -X package
并注意到这个宝石:
Forking command line: cmd.exe /X /C ""C:\Program Files\Java\jdk1.6.0_29\jre\bin\
java" -jar C:\Projects\my-project\target\surefire\surefirebooter2373372991878002
398.jar C:\Projects\my-project\target\surefire\surefire1861974777102399530tmp C:
\Projects\my-project\target\surefire\surefire4120025668267754796tmp"
好的,所以它正在运行 java 6。为什么?surefire 的文档给出了这个:
jvm:
Option to specify the jvm (or path to the java executable) to use with the forking
options. For the default, the jvm will be a new instance of the same VM as the one
used to run Maven. JVM settings are not inherited from MAVEN_OPTS.
由于我们使用 java 6 VM 运行 mvn,因此它分叉了 java 6 VM 进行单元测试。所以适当地设置这个选项:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.12</version>
<configuration>
<jvm>${JAVA_7_HOME}/bin/java</jvm>
</configuration>
</plugin>
并启动构建...
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------