【发布时间】:2013-03-19 06:33:32
【问题描述】:
我已经看到了Which JDK's distributions can run `javac -source 1.6 -target 1.5`? 中讨论的编译选项。我了解源和目标的各个选项。我不明白为什么源版本高于目标版本。为旧目标编译代码是有意义的。但是在那种情况下,我们为什么不直接使用 -source 我们希望能够在其上运行的最旧目标
【问题讨论】:
我已经看到了Which JDK's distributions can run `javac -source 1.6 -target 1.5`? 中讨论的编译选项。我了解源和目标的各个选项。我不明白为什么源版本高于目标版本。为旧目标编译代码是有意义的。但是在那种情况下,我们为什么不直接使用 -source 我们希望能够在其上运行的最旧目标
【问题讨论】:
确保还设置 bootclasspath 以确保您的程序可以在较旧的 VM 上运行。
来自javacdocumentation:
交叉编译示例
以下示例使用 javac 编译将在 1.6 VM 上运行的代码。
C\:>javac -source 1.6 -target 1.6 -bootclasspath C:\jdk1.6.0\lib\rt.jar -extdirs "" OldCode.java
-source 1.6选项指定使用 1.6(或 6)版 Java 编程语言编译OldCode.java。选项-target 1.6选项确保生成的类文件将与1.6 VM 兼容。请注意,在大多数情况下,-target选项的值是-source选项的值;在此示例中,您可以省略-target选项。您必须指定
-bootclasspath选项来指定引导类的正确版本(rt.jar库)。如果不是,编译器会生成以下警告:C:\>javac -source 1.6 OldCode.java warning: [options] bootstrap class path not set in conjunction with -source 1.6如果您没有指定正确的引导类版本,编译器将使用旧的语言规则(在本例中,它将使用 Java 编程语言的 1.6 版)结合新的引导类,这可能会导致在旧平台(在本例中为 Java SE 6)上无法使用的类文件,因为可以包含对不存在的方法的引用。
【讨论】:
Java 向后兼容。您使用 -source 选项指定用于编译的 java 版本,并使用 -target 选项指定要支持的最低 java 版本。例如。如果我指定 1.4 的目标,那么我的程序将无法在 java 1.3 或更低版本上运行。有关更多信息,请参阅以下 javac documentation。尤其是关于交叉编译选项
的部分【讨论】:
-source 1.8 -target 1.7 是否能够让我的代码在 Java 7 中正常运行?
Peter Tseng 在编译过程中确实提到了很多要记住的关键点。事实上,即使我曾经也遇到过类似的问题,并且想分享许多问题的根本原因。
我有一个必须编译并使其兼容的源代码(-source 和 -target)Java '1.8'。代码本身有
java.sql.* 包的大量更改经过某些更改后,我最终得到了一个运行相同数量的 JUnit 测试用例的代码。最终我遇到了java.lang.VerifyError。当我了解到当我在不同的库/环境中编译和运行代码时会发生这种错误时,我感到很震惊(事实并非如此)。
我几乎错过的是,为了纪念测试必须在隔离环境中运行这一事实,Junit 及其测试用例在单独的分叉 VM 中执行
<target name="runJunit">
<junit printonsummary="on"
haltonfailure="off"
fork="true"
forkmode="once">
<formatter />
<batchtest />
<classpath />
</junit>
</target>
这显然将作为一个单独的进程跨越并作为一个独立的应用程序执行。尽管 IDE 同步跨越两个进程,但 JVM 几乎是隔离的。
在 Java 1.7 之后,Oracle 引入了更严格的验证并稍微改变了类格式——包含一个堆栈映射,用于验证代码是否正确。我看到的异常是因为某些方法没有有效的堆栈映射。我最终尝试包含许多 JVM 选项来调整设置,但徒劳无功。
<jvmarg value="bootclasspath:{env.JAVA_HOME}\jre\bin\rt.jar" prefix="-X"/>
没有任何效果。唯一的解决方法是包含
<jvmarg value=":UseSplitVerifier" prefix="-XX"/>
在 Java 1.7 中只允许名义上的字节码验证。由于这是在 Java 1.8 中取消的,唯一的选择是使用
<jvmarg value="-noverify"/>
【讨论】:
JDK1.8 将不再支持 -source 和 -target 小于 1.6
"c:\Program Files\Java\jdk1.8.0_121\bin\javac.exe" -source 1.3 HelloWorld.java
warning: [options] bootstrap class path not set in conjunction with -source 1.3
warning: [options] source value 1.3 is obsolete and will be removed in a future release
warning: [options] target value 1.4 is obsolete and will be removed in a future release
warning: [options] To suppress warnings about obsolete options, use -Xlint:-options.
4 warnings
【讨论】: