我了解版本 JDK X 生成的字节码保证可以在 JVM Y 上工作,前提是 Y >= X。
这适用于所有版本的 JDK/JVM 吗?即期望 JDK 1 生成的类文件在 JVM 11 上工作是否公平?
参考JVM 规范、JDK 8 兼容性指南和Java 11 JSR 无法找到准确的答案。
我了解版本 JDK X 生成的字节码保证可以在 JVM Y 上工作,前提是 Y >= X。
这适用于所有版本的 JDK/JVM 吗?即期望 JDK 1 生成的类文件在 JVM 11 上工作是否公平?
参考JVM 规范、JDK 8 兼容性指南和Java 11 JSR 无法找到准确的答案。
字节码本身应该可以在未来的版本中使用。直到现在,这都是正确的,但没有人知道这是否适用于所有未来。
什么变化,并且可能破坏你的程序,是 API 的变化。不推荐使用的 API 将来可能会消失,然后您的程序将不再工作,并且java.lang.NoSuchMethodError
在引用此类方法时可能会抛出 a。
Java 字节码不向前兼容,JVM 向后兼容。这些属性之间的区别在于,任何未来的 JVM 都可能决定放弃向后兼容到某个较旧的字节码版本。
Java 字节码的设计方式很少需要这种删减,但是已经故意限制了向后兼容性。从 Java 8 开始,不再支持invokespecial
Java 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
早期版本的过时且现在不受支持的语义的代码才会中断。
另一个更改是指令jsr
和ret
已被删除¹,但是,此更改已与较新的类文件版本相关联,因此旧类文件版本仍支持这些指令,因此它不会破坏现有代码。但这可能是未来 JVM 确实放弃对这些旧版本的支持的一个原因。
如果
class
文件版本号为 51.0 或更高版本,则jsr操作码或jsr_w操作码都不会出现在code
数组中。
该ret
指令没有被提及,但没有jsr
指令就无法工作。