不同的JDK更新是否会生成不同的Java字节代码?
假设情景:
我有一个项目的源合规级别指定为1.5。 现在我用两个不同的JDK编译这个项目:首先使用JDK 6 Update 7,然后使用JDK 6 Update 20。
这两个不同的JDK是否会生成不同的Java字节代码,尽管它们的Update版本只有不同?
生成的代码通常仅在编译器错误修复的情况下有所不同。
但是,JLS 没有指定从源代码到生成的字节代码的1:1映射,因此您不应该依赖于生成完全相同的字节代码。
没有什么可以阻止不同版本生成不同的字节码,只要它符合JLS中指定的行为即可 。 JLS留下了许多实现细节,从一个实现到另一个实现。
让我们从另一方面回答:不能保证任何两个版本的jdk产生相同的字节代码。 所以你可以期待一般的差异。
如果至少在某些情况下它没有导致更改字节代码,那么为什么地球上有人会遇到发布更新开发工具包的麻烦? 我强烈怀疑是否有人会为了文档更新而这样做。
字节码可能略有不同,但这不用担心,因为它仍然是兼容的。
真正要执行的是取决于JIT。
例如JDK 6 Update 7的编译器可能输出与JDK 6 Update 20的编译器略有不同的字节码,但由于它是Java 6,因此类文件将完全兼容 – 您将能够运行使用Update 20编译的代码更新7没有任何问题。
在主要Java版本(例如Java 5与Java 6)之间可能存在更改,因此在较新版本上编译的代码将无法在旧版本上运行。 例如,对于Java 7,很可能会出现一个新指令invokedynamic 。 包含该指令的类文件将无法在较旧的Java版本上运行。
但是,更新版本之间从未进行过如此大的更改。
正如通常用于不同的编译器一样,它也是在Java情况下:结果必须相同,但它的到达方式可以(从字节码的角度来看)不同,例如由于优化或类似。 JVM是基于堆栈的V机器; 以下是一个虚构的例子(我不知道jvm助记符的指令操作码)
推10 推20 加
推19 推1 加 推10 加
这些产生相同的结果,但生成的字节码是不同的(第一个稍微优化,第二个是“完全”未优化;第三个选项可能是push 30
因为我们添加已知(可能在编译时)常量)。 这是一个简单的案例,但可以轻松构建更复杂的案例。
如果使用不同的JDK版本进行编译,我建议使用javac的target选项。 否则,您可能无法使用较旧的JDK运行jar。
您可能还想使用javac的source选项,以确保开发人员不使用在最近的JDK中添加的类/方法。