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

时间:2008-09-30 12:07:54

标签: java serialization

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

8 个答案:

答案 0 :(得分:16)

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

类似的东西:

private static final long serialVersionUID = 8683452581122892189L;

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

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

  

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

答案 1 :(得分:3)

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

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

答案 2 :(得分:2)

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

答案 3 :(得分:2)

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

答案 4 :(得分:2)

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

答案 5 :(得分:2)

您是否阅读过Java Object Serialization Specificationversioning上有一个主题。还有一篇针对课程实施者的文章:Discover the secrets of the Java Serialization API。每个Java版本都附带compatibility notes

关于序列化的Java 6规范:


目标是:

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

答案 6 :(得分:0)

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

查看XMLEncoderXMLDecoder类的文档。

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

答案 7 :(得分:0)

混合使用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)