Java版本之间是否存在后向不兼容的具体示例?

时间:2009-10-31 16:55:05

标签: java jvm bytecode backwards-compatibility

Java版本之间是否存在不兼容性,其中针对Java版本X的Java源代码/ Java类文件无法在版本Y下编译/运行(其中Y> X)?

“Java发布”是指版本如:

  • JDK 1。0(1996年1月)
  • JDK 1。1(1997年2月)
  • J2SE 1。1(1998年12月)
  • J2SE 1。3(2000年5月)
  • J2SE 1。1(2002年2月)
  • J2SE 5。0(2004年9月)
  • Java SE 6(2006年12月)

众议院规则:

  • 请尽可能包含参考和代码示例。
  • 请在答案中尽量具体/具体。
  • 标记为@Deprecated的类不算作向后不兼容。

14 个答案:

答案 0 :(得分:24)

各种版本的兼容性说明:

我记得的第一个主要打嗝是在Java 1.4中引入assertIt affected a lot of JUnit code

答案 1 :(得分:19)

首先,Sun实际上认为您提到的所有版本(当然不是1.0)都是次要版本,而不是主要版本。

我不知道那时候二进制不兼容的任何例子。但是,有一些源不兼容的例子:

  • 在Java 5中,“enum”成为一个保留字;它不是之前。因此,有一些源文件使用枚举作为标识符,将在java 1.4中编译,不能在java 5.0中编译。但是,您可以使用-source 1.4进行编译以解决此问题。

  • 向接口添加方法也会破坏源兼容性。如果您实现了一个接口,然后尝试使用向接口添加新方法的JDK编译该实现,则源文件将不再成功编译,因为它不会实现所有接口的成员。 java.sql.Statement和其他jdbc接口经常发生这种情况。除非您实际调用其中一个不存在的方法,否则这些“无效”实现的编译形式仍然有效;如果你这样做,将抛出一个MissingMethodException。

这些是我可以回想起的一些例子,可能还有其他例子。

答案 2 :(得分:15)

接口java.sql.Connection已从Java 1.5扩展到Java 1.6,使得实现此接口的所有类的编译失败。

答案 3 :(得分:11)

Swing的每一个版本都为我们打破了一些东西,从1.3到1.6。

已经提到过JDBC问题,但现有代码已经运行。

从1.5到1.6,Socket的行为发生了变化,打破了思科客户端。

当然会引入新的保留关键字。

我认为在Sun方面真正不可原谅的一个重要因素是System.getenv()。它在1.0中运行,然后被弃用并更改为在所有平台上抛出错误,这是因为Mac没有系统环境变量。然后Mac得到了系统环境变量,因此在1.5中它没有被提及并且有效。这样做没有合理的理由。在Mac上返回一个空集(如果你想关心那个级别的跨平台一致性,Swing有更大的跨平台问题),甚至在所有平台上。

我从不同意他们关闭这个功能,但改变它以引发错误只是一个纯粹的改变,如果他们要做的话,他们应该完全删除该方法。

但是,实际上从1.0到1.1他们不太关心向后兼容性。例如,他们将“private protected”作为修饰符。

所以结果就是每个版本都有足够的变化需要仔细评估,这就是为什么你在SO上仍然会看到很多1.4问题的原因。

答案 4 :(得分:10)

我能想到的主要是引入新的保留字:

Java 1.3: strictfp
Java 1.4: assert
Java 5.0: enum

以前使用这些值作为标识符的任何代码都不会在更高版本下编译。

我记得在我所处理的项目中导致问题的另一个问题是a change in the default visibility of JInternalFrames between 1.2 and 1.3。它们默认是可见的,但是当我们升级到1.3时,它们似乎都消失了。

答案 5 :(得分:8)

在1.3和1.4之间,Long.parseLong(String)的解释以不同方式处理空字符串。 1.3返回0值,而1.4则返回NumberFormatException

不需要重新编译,但如果依赖于1.3行为,则工作代码停止工作。

答案 6 :(得分:7)

memory model changed from 1.4 to 1.5的语义。它被改为允许除了其他东西再次双重检查锁定。 (我认为易失性语义是固定的。)它被打破了。

答案 7 :(得分:4)

以下内容将在Java 1.4下编译,但不是 Java 1.5或更高版本。

(Java 5引入了'enum'作为关键字。注意:如果提供了“-source 1.4”选项,它将在Java 5中编译。)

public class Example {
    public static void main(String[] args) {
        String enum = "hello";
    }
}

答案 8 :(得分:4)

显然release names的命名惯例是not backwards-compatible

  • JDK 1。0(1996年1月23日)
  • JDK 1。1(1997年2月19日)
  • J2SE 1。1(1998年12月8日)
  • J2SE 1。3(2000年5月8日)
  • J2SE 1。1(2002年2月6日)
  • J2SE 5。0(2004年9月30日)
  • Java SE 6(2006年12月11日)
  • Java SE 6 Update 10,Update 12,Update 14,Update 16
  • Java SE 7 ??? JDK7?

The list is from Wikipedia。)

答案 9 :(得分:3)

java.sql破坏兼容性的又一个例子:

在1.5中,compareTo(Date)方法被添加到java.sql.Timestamp中。如果提供的Date不是java.sql.Timestamp的实例,则此方法将抛出ClassCastException。当然,java.sql.Timestamp扩展了Date,而Date已经有了一个适用于所有日期的compareTo(Date)方法,所以这意味着将Timestamp与(非时间戳)Date进行比较的代码将在1.5中在运行时中断

值得注意的是,似乎1.6似乎解决了这个问题。虽然java.sql.Timestamp.compareTo(Date)的文档仍然显示“如果参数不是Timestamp对象,则此方法抛出ClassCastException对象”,实际实现则另有说明。我的猜测是这是一个文档错误。

答案 10 :(得分:3)

请在此处查看有关JRE类库的API更改的报告:http://abi-laboratory.pro/java/tracker/timeline/jre/

该报告包括对Java类的后向二进制和源兼容性分析。

该报告由 japi-compliance-checker 工具生成。

enter image description here

...

enter image description here

您可以在Japitools JDK-Results页面找到另一个有趣的JDK 1.0-1.6分析。

答案 11 :(得分:2)

正如Sean Reilly所说,一种新方法可能会破坏你的代码。除了你必须实现一个新方法(这将产生编译器警告)的简单情况之外,最糟糕的情况是:接口中的新方法具有相同的签名作为您已经拥有的方法在你的班上编译器的唯一提示是缺少@Override注释的警告(类5的Java 5,Java 6中的接口支持注释,但是可选)。

答案 12 :(得分:2)

我还没有尝试过,但理论上这可以在Java 1.1中运行并在Java 1.2中中断。 (更多info here

public class Test {
    float strictfp = 3.1415f;
}

答案 13 :(得分:1)

根据个人经验,我们在1.5中的SWT_AWT框架中嵌入了一些AWT / Swing文本字段,在升级到1.6后不再可编辑。