使用JDK8编译目标JRE7

时间:2014-07-07 09:44:20

标签: java maven

到目前为止,我认为编译的-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上使用“:”。怎么解决?

3 个答案:

答案 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模块配置交叉编译:

  • 即使目标JDK不存在,也允许编译。
  • 当目标JDK存在时自动使用交叉编译。

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>