在为旧版Java进行交叉编译时,在哪里可以找到引导类?

asa*_*evs 8 java javac cross-compiling

我们有一个Java项目,我们希望分发给用户.它不使用Java 1.5之外的任何Java功能,因此我们希望它在Java 1.5及更高版本上运行.

此时,您可能正确地注意到Java 1.6是目前最早的可用,那么为什么要定位Java 1.5呢?但是,这并没有改变旧版本交叉编译问题的一般性质.

因此,通常开始交叉编译尝试的方式是指定-source 1.5-target 1.5选项javac,此时会得到一个关于-bootclasspath未设置的着名警告:

$ javac -source 1.5 -target 1.5 Test.java 
warning: [options] bootstrap class path not set in conjunction with -source 1.5
1 warning
Run Code Online (Sandbox Code Playgroud)

现在,根据Oracle博客文章以及官方文档,交叉编译的正确做法是:

要使用JDK N中的javac交叉编译到较旧的平台版本,正确的做法是:

  • 使用较旧的-source设置.
  • 将bootclasspath设置为针对旧平台的rt.jar(或等效项)进行编译.

如果不采取第二步,javac将尽职尽责地使用旧语言规则与新库相结合,这可能导致类文件无法在旧平台上运行,因为可以包含对不存在的方法的引用.

例如,引用官方文档:

% javac -source 1.6 -target 1.6 -bootclasspath jdk1.6.0/lib/rt.jar \
    -extdirs "" OldCode.java
Run Code Online (Sandbox Code Playgroud)

这很好,并且在Stack Overflow和Internet的其他部分之前已经多次回答.

但是,我们发现的资源似乎都没有表明在哪里可以找到rt.jar旧版本的Java.例如,rt.jar除了自己的JDK 1.7 之外,JDK 1.7不附带:

$ find jdk-1.7.0_45 -name rt.jar
jdk-1.7.0_45/jre/lib/rt.jar
Run Code Online (Sandbox Code Playgroud)

这使人们认为,例如,为了获得rt.jarJava 1.6,需要下载JDK 1.6.但后来出现了两个问题:

  1. 如果我们下载JDK 1.6,我们不妨用它来编译而不是JDK 1.7;
  2. 如果我们希望交叉编译Java 1.5,那么JDK 1.5将不再可供下载.

那么,我们如何实际指定-bootclasspath使用此交叉编译功能的选项?

Boy*_*Jr. 0

此类编译的主要动机是需要针对已投入生产的 JRE 或其他现有安装 IME。在这种情况下,第一个任务是从现有安装中提取 JRE bootclasspath 文件并使其可从构建系统中使用。您指定的 bootclasspath 值将取决于您在该步骤中放置 JRE bootclasspath 文件的位置。

仅供参考,您可能需要的文件不仅仅是 rt.jar。例如,当针对 IBM Java 6 时。