问题 使用不同版本的JDK编译Java以及相同的目标和源版本是否保证相同的执行?


我们将更新我们的CI系统,该系统创建从Java 7到Java 8的构建。稍后我们希望将项目逐个迁移到Java 8。当然,我们希望能够为仍使用Java 7的旧版本创建bugfix版本。

如果我们将构建相同的源,目标版本和源版本从JDK 7转移到JDK 8,我们能否确定不会出现任何问题?我们对开发机器进行了测试,没有任何问题。

在此之前,我们还逐步将部署服务器从JRE 7更新到JRE 8。

请注意,我们希望在CI系统上保持单个Java JDK安装,否则会变得复杂。

为了更清楚: 我对相同的执行结果更感兴趣,而不是相同的字节码。如果我理解正确的话,相同的字节码只会确认第一个(在相同的JRE上运行)。

在我们在Java 8上运行所有部署之前,我们不会在代码中使用Java 8功能。因此兼容性不是问题。


902
2018-03-30 14:12


起源

我将假设它不会生成相同的字节码,因为使用相同的JDK编译也可能不会生成相同的字节码。虽然针对相同目标和源版本的相同代码的执行结果将是相同的。 - apokryfos
我认为你真正想知道的不是两个类文件在逐字节比较中是否具有相同的字节代码,而是使用jdk8创建的所有类文件 - -source / -target设置为1.7将是是 兼容 与所有较旧的类文件,实用程序,框架等。是吗? - Klitos Kyriacou
@KlitosKyriacou不太好。您还需要将bootclasspath明确设置为JDK 7; -source/-target 设置语言水平但是 不 图书馆水平。 - Louis Wasserman
@ LouisWasserman的评论提出了一个问题 巨大 很重要的一点。小心这个。图书馆很重要。 - Erick G. Hagstrom
@KlitosKyriacou完全正确。兼容和相同的执行因为我们不想遇到任何奇怪的错误,因为编译器在不同的JDK中的工作方式不同。 - coldman


答案:


使用不同版本的JDK和相同的目标和源版本编译Java是否会产生相同的字节码?

没有保证。

实际上,使用相同编译器在相同硬件上使用相同选项从相同源代码创建的两个.class文件将具有相同的字节码,但由于嵌入式编译时间戳属性,文件可能仍然不同。

但是,如果您想比较概念上等效的字节码文件,这个Q&A提供了一些可能的线索:


我希望你  发现Java 7和Java 8编译器生成的字节码之间存在一些差异,但这并不重要。


9
2018-03-30 14:25





如此规定 博客@ HTTPS://blogs.oracle.com/darcy/entry/source_target_class_file_version

给定相同的源代码,来自不同版本的编译器配置为使用相同的源和相同的目标(以及相同的bootclasspath!),由于错误修复或编译器内部合同的更改,仍然可以生成不同的类文件。

但是这个问题不会发生在你身上,因为你有相同的编译器可以编译成不同的目标版本。 它只需要发出与该版本兼容的特定幻数和字节代码。看起来像保持1.8版本的版本,并指定较低或相同版本的目标将起作用。看看这个过去已经解决的缺陷,看来它应该可行,而Oracle正在努力解决这些不兼容问题。 http://bugs.java.com/bugdatabase/view_bug.do?bug_id=4175911

应该有助于的其他资源:

  1. http://www.javaworld.com/article/2077388/core-java/what-version-is-your-java-code.html?page=2
  2. http://www.oracle.com/technetwork/java/javase/8-compatibility-guide-2156366.html

4
2018-03-30 15:07



OP正在询问不同的情况 javac 版本和相同的源/目标级别。不一样 javac 和不同的源/目标水平。 - Stephen C
“在CI系统上安装单个Java JDK”推断出一个javac。 - randominstanceOfLivingThing
这意味着一次一个。他还说: “我们将更新我们的CI系统,该系统可以创建从Java 7到Java 8的构建。” - Stephen C
我不认为构建服务器需要多个JDK来创建从Java 7到Java 8的构建。 - randominstanceOfLivingThing
我同意。但这不是重点。 OP担心当他用Java 8替换Java 7时会发生什么。具体来说......升级可能会导致问题,因为Java 7 javac和Java 8 javac正在生成不同的字节码。我的看法是1)字节码很可能存在差异,但2)这不太可能导致问题。 - Stephen C


是啊!它实际上取决于代码。在某些情况下,它可能会生成不同的字节码,但通常情况下它会生成相同的字节码。

不同的JDK将具有不同的Java编译器,这些Java编译器可以为相同的源代码发出不同的字节码。 javac编译器随着时间的推移而发展。

Java的不同主要版本通常会发出符合类文件规范的不同版本的类文件。

即使您将自己限制为一个JDK安装,在同一源文件上运行两次编译器也会生成不同的.class文件。


1
2018-03-30 14:36