到目前为止,我认为编译的-target
参数足以确保我的应用程序即使使用JDK8 javac进行编译也能在JRE7上执行。
当我了解Sun / Oracle如何将方法签名从一个版本更改为另一个版本时,我很快变得更加明智。
我的目标是 - 使用JDK8工具链 - 创建一个将同时使用JRE7和JRE8执行的二进制文件。我工作的构建农场是多操作系统,这意味着有些是Windows,有些是Solaris等。我无法事先预测应用程序的构建位置。
我理解推荐的解决方案是在编译步骤中使用-Xbootclasspath
。我正在使用Maven所以我需要这样的东西:
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.1</version>
<configuration>
<source>1.7</source>
<target>1.7</target>
<compilerArguments>
<bootclasspath>XXXX</bootclasspath>
</compilerArguments>
</configuration>
</plugin>
</plugins>
</build>
我不明白的是如何设置XXXX
以便我的应用程序可以在任何地方构建,而不仅仅是在我自己的工作站上。基本上我希望XXXX成为一个工件或依赖,如果你愿意。我无法控制目标构建机器,但我可以将第三方工件上传到我们的公司Maven仓库。如何解决这个问题?
我看到的另一个问题是XXXX真的是一个列表。它不是一个罐子。 (据我所知 - 为了安全 - 它确实是来自目标JRE的sun.boot.class.path
的价值,这意味着它不仅仅是rt.jar
,正如一些文献似乎所暗示的那样)。如何设置XXXX以使其独立于操作系统,假设“;”在Windows上用作列表项分隔符,而在Unix / Linux上使用“:”。怎么解决?
答案 0 :(得分:2)
您可以尝试个人资料
<profiles>
<profile>
<id>default</id>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<properties>
<bootclasspath>xxx</bootclasspath>
</properties>
</profile>
<profile>
<id>win</id>
<activation>
<os>
<family>Windows</family>
</os>
</activation>
<properties>
<bootclasspath>yyy</bootclasspath>
</properties>
</profile>
</profiles>
答案 1 :(得分:0)
我建议不要交叉编译,而是要实际使用你想构建的JDK。
如果此JDK版本与项目的其他版本不同,请使用Maven工具链插件。
答案 2 :(得分:0)
假设maven本身在JDK 8下运行,但目的是编译模块以与JDK 7兼容。
正确的交叉编译要求目标JDK存在。请考虑以下方法为特定Maven模块配置交叉编译:
Maven无法自行检测其他JDK的存在,因此您必须定义环境属性(下例中的JDK7_HOME
),这将触发交叉编译配置文件并提供基本路径用于bootclasspath
配置。
<build>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.1</version>
</plugin>
</plugins>
</pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<!--
the base config should generate class files
with the proper version number
even in the absence of cross-compilation JDK
-->
<source>1.7</source>
<target>1.7</target>
</configuration>
</plugin>
</plugins>
</build>
<profiles>
<profile>
<id>cross-compile-jdk7</id>
<activation>
<property>
<!--
the proper cross-compilation is triggered
when the cross-compilation JDK is really present
-->
<name>env.JDK7_HOME</name>
</property>
</activation>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<!--
the advanced config not only generates class files
with the proper version number
but also uses correct bootclasspath
-->
<source>1.7</source>
<target>1.7</target>
<!--
forking is required for when changing bootclasspath
-->
<fork>true</fork>
<!--
the following monstrosity is the most paranoid way
to get correct file and path separators
this particular example includes rt.jar and jsse.jar
from the target JDK
-->
<compilerArgs>
<arg>-bootclasspath</arg>
<arg>${env.JDK7_HOME}${file.separator}jre${file.separator}lib${file.separator}rt.jar${path.separator}${env.JDK7_HOME}${file.separator}jre${file.separator}lib${file.separator}jsse.jar</arg>
</compilerArgs>
</configuration>
</plugin>
</plugins>
</build>
</profile>
</profiles>