Java 二进制兼容性发生了什么变化?

What happened to Java Binary Compatibility?

我在 1997 年 3 月发现了一套旧的 classes。那是我尝试学习 Java 的时候,它是 JDK 1.0.2

有趣的是,我的源文件和 class 文件都完好无损。源代码仍然按预期编译和执行,这真的很酷。但是 Java 不应该也保留二进制兼容性吗?好吧,在这个过程中的某个地方,格式不再有效。 A Java 8 VM 将报告;

Exception in thread "main" java.lang.ClassFormatError: Invalid start_pc 65535 in LocalVariableTable in class file bali/core/Application
    at java.lang.ClassLoader.defineClass1(Native Method)
    at java.lang.ClassLoader.defineClass(ClassLoader.java:760)
    at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:142)
    at java.net.URLClassLoader.defineClass(URLClassLoader.java:455)
    at java.net.URLClassLoader.access0(URLClassLoader.java:73)
    :
    [snip many ClassLoader calls]
    :
    at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
    at sun.launcher.LauncherHelper.checkAndLoadMain(LauncherHelper.java:495)

有问题的 class 是我从命令行调用的 class 的超级 class。

再说一个细节,那时候微软还在Java阵营,我记得他们的javac对写得不好的语法比较顺从。 Sun 编译器很乐意接受 "public synchronized class Abc" 和许多其他无效语句。因此,这些 class 文件很有可能是由 MS 编译器生成的,然后 运行 在 Sun JVM 上。

无论如何,我的问题是;有没有人知道Java早期版本的兼容性承诺?是大事,还是故意牺牲的?还是很久以后才做出决定,比如 Java 1.4 或 Java 5 只是放弃 JDK 1.0 支持?

正如您提到的,当编译器从 Microsoft 编译器切换到 Sun 编译器时,可能会引入该问题。 Sun 声明 Microsoft 编译器生成的 class 文件不符合 Java 规范,因此无效。

您可以找到更多详细信息here:

This error is caused by bytecode generated from old JDK 1.0.2 or 1.1 compilers. In the past, a lot of these compilers generated bytecode that does not conform to the Java VM Specification. Since the verifiers in recent J2SE releases are much stricter about bad class format, the ClassFormatError is thrown by the VM when these bad class files are loaded.

关于一般性问题,Java 仍然坚定地致力于向后兼容,从未有过重大突破。在边缘问题上,从一个版本到另一个版本通常会有轻微的中断。我知道没有大师 table 但这里有 table 个别版本:

  • Java 8(与 Java 7 完全二进制兼容)
  • Java 7(主要与 Java 6 二进制兼容)
  • Java 6(主要与 Java 5 二进制兼容,加上一些混淆器生成规范之外的 class 文件的评论,因此这些 class 文件可能不会 运行)
  • Java 5(主要与 Java 1.4.2 二进制兼容,加上关于混淆器的相同注释)
  • Java 1.0 - 1.4.2(主要与以前的版本二进制兼容,一些向前兼容的评论甚至可能有效但未经过测试)