java对象序列化是否在1.5和1.6之间兼容

我想知道混合jdk 1.5和1.6(Java 6)对象序列化(biderctional通信)是否安全。 我搜索了太阳关于这个问题的明确声明,但没有成功。 因此,除了技术可行性之外,我正在寻找关于该问题的“官方”声明。

序列化机制本身并没有改变。 对于个别课程,它将取决于具体的课程。 如果类具有serialVersionUID字段,则应该指示序列化兼容性。

就像是:

private static final long serialVersionUID = 8683452581122892189L; 

如果不变,则序列化版本兼容。 对于JDK类,这是有保证的,但当然总是可能在进行重大更改后忘记更新serialVersionUID。

当JDK类不能保证兼容时,这通常在Javadoc中提到。

警告:此类的序列化对象与以后的Swing版本不兼容

1.5和1.6中的序列化机制是兼容的。 因此,在1.5和1.6上下文中编译/运行的相同代码可以交换序列化对象。 两个VM实例是否具有相同/兼容的类版本(可能由serialVersionUID字段指示)是与JDK版本无关的不同问题。

如果你有一个可序列化的Foo.java并在1.5和1.6 JDK / VM中使用它,那么由一个V创建的Foo的序列化实例; 可以被另一个反序列化。

在使用Java 1.5程序中的ObjectOutputStream将序列化对象写入文件进行测试之后,然后在Java 1.6程序中运行带有ObjectInputStream的读取,我可以说这没有任何问题。

我会很快补充说,可以更改类但忘记更改serialVersionUID。 因此,“如果类定义了一个serialVersionUID,并且这不会改变,则保证类兼容是不正确的。” 相反,拥有相同的serialVersionUID是API承诺向后兼容的方式。

除非另有说明,否则这应该是二进制兼容性的一部分。 Swing类在版本之间明显不兼容。 如果您发现其他类有问题,请报告bugs.sun.com上的错误。

您是否阅读过Java对象序列规范 ? 版本控制有一个主题。 还有一篇针对类实现者的文章: 发现Java Serialization API的秘密 。 每个Java版本都附带兼容性说明 。

从序列化的Java 6规范:


目标是:

  • 通过以下方式支持在不同虚拟机中运行的类的不同版本之间的双向通信:
    • 定义一种机制,允许JavaTM类读取由同一类的旧版本编写的流。
    • 定义一种机制,允许JavaTM类编写要由同一类的旧版本读取的流。
  • 为持久性和RMI提供默认序列化。
  • 在简单的情况下表现良好并生成紧凑的流,以便RMI可以使用序列化。
  • 能够识别和加载与用于编写流的确切类相匹配的类。
  • 保持非版本化类的开销很低。
  • 使用允许遍历流的流格式,而不必调用特定于流中保存的对象的方法。

请注意,Java Beans规范详细说明了与版本无关的序列化方法,该方法允许强大的向后兼容性。 它还导致可读的“序列化”forms。 实际上,使用该机制可以非常容易地创建序列化对象。

查找XMLEncoderXMLDecoder类的文档。

我不会使用它来通过线路传递对象(虽然如果要求高性能,我也不会使用序列化)但它对于持久对象存储非常有用。

混合Java 1.5和1.6是不安全的。 例如,我将一个Java 1.5对象序列化为一个文件并尝试在Java 1.6中打开它,但它提出了下面的错误。

 java.io.InvalidClassException: javax.swing.JComponent; local class incompatible: stream classdesc serialVersionUID = 7917968344860800289, local class serialVersionUID = -1030230214076481435 at java.io.ObjectStreamClass.initNonProxy(Unknown Source) at java.io.ObjectInputStream.readNonProxyDesc(Unknown Source) at java.io.ObjectInputStream.readClassDesc(Unknown Source) at java.io.ObjectInputStream.readNonProxyDesc(Unknown Source) at java.io.ObjectInputStream.readClassDesc(Unknown Source) at java.io.ObjectInputStream.readNonProxyDesc(Unknown Source) at java.io.ObjectInputStream.readClassDesc(Unknown Source) at java.io.ObjectInputStream.readOrdinaryObject(Unknown Source) at java.io.ObjectInputStream.readObject0(Unknown Source) at java.io.ObjectInputStream.readArray(Unknown Source) at java.io.ObjectInputStream.readObject0(Unknown Source) at java.io.ObjectInputStream.defaultReadFields(Unknown Source) at java.io.ObjectInputStream.readSerialData(Unknown Source) at java.io.ObjectInputStream.readOrdinaryObject(Unknown Source) at java.io.ObjectInputStream.readObject0(Unknown Source) at java.io.ObjectInputStream.defaultReadFields(Unknown Source) at java.io.ObjectInputStream.readSerialData(Unknown Source) at java.io.ObjectInputStream.readOrdinaryObject(Unknown Source) at java.io.ObjectInputStream.readObject0(Unknown Source) at java.io.ObjectInputStream.readArray(Unknown Source) at java.io.ObjectInputStream.readObject0(Unknown Source) at java.io.ObjectInputStream.defaultReadFields(Unknown Source) at java.io.ObjectInputStream.readSerialData(Unknown Source) at java.io.ObjectInputStream.readOrdinaryObject(Unknown Source) at java.io.ObjectInputStream.readObject0(Unknown Source) at java.io.ObjectInputStream.readObject(Unknown Source)