java字节码是否始终向前兼容?

时间:2018-03-23 08:59:52

标签: java jvm compatibility jvm-bytecode

据我所知,版本JDK X生成的字节代码可以保证在JVM Y上工作,只要Y> = X。

这对所有版本的JDK / JVM都有用吗? 期望JDK 1生成的类文件在JVM 11上运行是否公平?

提到JVM specsJDK 8 compatibility guideJava 11 JSR 在那里找不到准确的答案。

2 个答案:

答案 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过时且现在不受支持的语义的代码才会中断。

另一个变化是指令jsrret已被删除¹但是,此更改已绑定到较新的类文件版本,因此旧版类文件版本仍支持这些说明,因此它不会破坏现有代码。但这可能是未来JVM放弃对这些旧版本的支持的原因。

¹JVM spec §4.9.1

  

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

尚未提及ret指令,但如果没有jsr指令则无效。