据我所知,版本JDK X生成的字节代码可以保证在JVM Y上工作,只要Y> = X。
这对所有版本的JDK / JVM都有用吗? 期望JDK 1生成的类文件在JVM 11上运行是否公平?
提到JVM specs,JDK 8 compatibility guide和Java 11 JSR 在那里找不到准确的答案。
答案 0 :(得分:4)
字节码本身应该适用于未来的版本。到目前为止,这是正确的,但没有人知道这对所有未来是否都是真的。
API的变化是什么变化,并且可能会破坏您的程序。过时的API可能会在将来消失,然后您的程序将不再起作用,并且在引用此类方法时可能会抛出java.lang.NoSuchMethodException
。
答案 1 :(得分:3)
Java字节代码不向前兼容,JVM向后兼容。这些属性之间的区别在于,任何未来的JVM都可能决定向后兼容某个较旧的字节代码版本。
Java字节代码的设计方式很少需要这种剪切,但已经存在对后向兼容性的故意限制。从Java 8开始,已经删除了对Java 1.0的invokespecial
的不同语义的支持。正如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
指令则无效。