6

我了解版本 JDK X 生成的字节码保证可以在 JVM Y 上工作,前提是 Y >= X。

这适用于所有版本的 JDK/JVM 吗?即期望 JDK 1 生成的类文件在 JVM 11 上工作是否公平?

参考JVM 规范JDK 8 兼容性指南Java 11 JSR 无法找到准确的答案。

4

2 回答 2

5

字节码本身应该可以在未来的版本中使用。直到现在,这都是正确的,但没有人知道这是否适用于所有未来。

什么变化,并且可能破坏你的程序,是 API 的变化。不推荐使用的 API 将来可能会消失,然后您的程序将不再工作,并且java.lang.NoSuchMethodError在引用此类方法时可能会抛出 a。

于 2018-03-23T09:10:42.513 回答
5

Java 字节码不向前兼容,JVM 向后兼容。这些属性之间的区别在于,任何未来的 JVM 都可能决定放弃向后兼容到某个较旧的字节码版本。

Java 字节码的设计方式很少需要这种删减,但是已经故意限制了向后兼容性。从 Java 8 开始,不再支持invokespecialJava 1.0 的不同语义。正如JVM Spec §4.1所述:

如果出现在此类或接口中,该ACC_SUPER标志指示由invokespecial指令 ( §invokespecial ) 表示的两种替代语义中的哪一种。Java 虚拟机指令集的编译器应设置该ACC_SUPER标志。在 Java SE 8 及更高版本中,Java 虚拟机认为ACC_SUPER要在每个class文件中设置标志,而不管文件中标志的实际值和class文件的版本class

ACC_SUPER标志的存在是为了向后兼容由 Java 编程语言的旧编译器编译的代码。在 1.0.2 之前的 JDK 版本中,生成的编译器access_flags现在表示的标志ACC_SUPER没有指定的含义,如果设置了标志,Oracle 的 Java 虚拟机实现会忽略该标志。

这并不意味着早期的 Java 1.0 代码不能正常工作。只有依赖于该invokespecial早期版本的过时且现在不受支持的语义的代码才会中断。

另一个更改是指令jsrret已被删除¹,但是,此更改已与较新的类文件版本相关联,因此旧类文件版本仍支持这些指令,因此它不会破坏现有代码。但这可能是未来 JVM 确实放弃对这些旧版本的支持的一个原因。


¹ JVM 规范 §4.9.1

如果class文件版本号为 51.0 或更高版本,则jsr操作码或jsr_w操作码都不会出现在code数组中。

ret指令没有被提及,但没有jsr指令就无法工作。

于 2018-03-23T18:03:31.557 回答