试验Java serilization

时间:2016-07-04 15:20:46

标签: java serialization version compatibility

我从概念上理解Java序列化,但是我对可序列化对象的版本兼容性感到非常困惑。当引用“版本”时,它是否意味着:

是两个层次关系的类,其中一个是属性的加/减?

或两个类符合不同的编译版本?

或两者兼而有之?

我的理解是我们必须保持suid一致,JVM会检查版本兼容性。

结果我设计了一个试验测试java序列化版本不兼容性的实验,代码片段如下,其中我使suid不同:

    public static class Incompatible implements Serializable {
    private static final long serialVersionUID = 1L;
    private int i;
    public Incompatible(int i){
        this.i = i;
    }
    public int getI(){
        return i;
    }
}

public static class IncompFoo extends Incompatible {
    private static final long serialVersionUID = 2L;
    public IncompFoo(int i){
        super(i);
    }
}

@Test
public void incompatibleTest() throws IOException, ClassNotFoundException{
    FileOutputStream fos = new FileOutputStream(new File("foo.ser"));
    ObjectOutputStream oos = new ObjectOutputStream(fos);
    oos.writeObject(new IncompFoo(10));
    oos.close();

    FileInputStream fis = new FileInputStream(new File("foo.ser"));
    ObjectInputStream ois = new ObjectInputStream(fis);
    Incompatible foo = (Incompatible)ois.readObject();
    ois.close();
    Assert.assertEquals(10, foo.getI());

}

我预计会出现InvalidClassException,因为这两个类有不同的suid。令我惊讶的是,测试完成了。

哪一部分错了?我们有一个简单的方法来创建InvalidClassException吗?

1 个答案:

答案 0 :(得分:1)

您的示例编写一个对象,读取它并将其强制转换为超类。没有什么有趣的事情发生在那里,即使你希望演员会以某种方式破坏事物(它不会,它只是一个演员和一个有效的演员)。

将该类的实例写入该文件,将其更改为serialVersionUID,重新编译该类并尝试重新读取序列化对象。忘掉任何超级/子类的恶作剧。