【问题标题】:Is java byte-code always forward compatible?java字节码总是向前兼容吗?
【发布时间】:2018-03-23 08:59:51
【问题描述】:

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

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

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

【问题讨论】:

  • 好吧,我们看不到未来,但到目前为止是的。

标签: java jvm compatibility jvm-bytecode


【解决方案1】:

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

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

【讨论】:

【解决方案2】:

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 虚拟机认为在每个 class 文件中设置了 ACC_SUPER 标志,而不管 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数组中。 p>

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

【讨论】:

    猜你喜欢
    • 2010-11-19
    • 2013-07-01
    • 2012-05-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多