开发者社区> 问答> 正文

字节序列反序列化问题

蛮大人123 2016-03-26 15:10:27 973

对象的字节序列存在硬盘上,更改了类的属性,反序列化时会造成不兼容问题。“但当serialVersionUID相同时,它就会将不一样的field以type的预设值反序列化,可避开不兼容问题”这句话什么意思?

分享到
取消 提交回答
全部回答(1)
  • 蛮大人123
    2019-07-17 19:16:17

    简单来说,Java的序列化机制是通过在运行时判断类的serialVersionUID来验证版本一致性的。在进行反序列化时,JVM会把传来的字节流中的serialVersionUID与本地相应实体(类)的serialVersionUID进行比较,如果相同就认为是一致的,可以进行反序列化,否则就会出现序列化版本不一致的异常。(InvalidCastException)。
    可以编写测试类:

    import java.io.Serializable;
    public class Serial implements Serializable {
        private static final long serialVersionUID = 6977402643848374753L;
        int id;
        String name;
    
        public Serial(int id, String name) {
            this.id = id;
            this.name = name;
        }
    
        public String toString() {
            return "DATA: " + id + " " + name;
        }
    
    }

    序列化测试代码:

     import java.io.FileNotFoundException;
    import java.io.FileOutputStream;
    import java.io.IOException;
    import java.io.ObjectOutputStream;
    
    public class SerialTest {
        public static void main(String[] args) {
            Serial serial1 = new Serial(1, "song");
            System.out.println("Object Serial" + serial1);
            try {
                FileOutputStream fos = new FileOutputStream("serialTest.txt");
                ObjectOutputStream oos = new ObjectOutputStream(fos);
                oos.writeObject(serial1);
                oos.flush();
                oos.close();
            } catch (FileNotFoundException e) { // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (IOException e) { // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    }

    反序列化测试代码:

     import java.io.FileInputStream;
    import java.io.FileNotFoundException;
    import java.io.IOException;
    import java.io.ObjectInputStream;
    
    public class DeserialTest {
        public static void main(String[] args) { // TODO Auto-generated method stub
            Serial serial2;
            try {
                FileInputStream fis = new FileInputStream("serialTest.txt");
                ObjectInputStream ois = new ObjectInputStream(fis);
                serial2 = (Serial) ois.readObject();
                ois.close();
                System.out.println("Object Deserial" + serial2);
            } catch (FileNotFoundException e) { // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (IOException e) { // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (ClassNotFoundException e) { // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    }

    可以测试待序列化类Serial设置了版本号,分别运行SerialTest和DeserialTest类后,如果修改Serial类添加一个属性int age,那么再执行DeserialTest的时候还是能够正确运行的。但是如果注释掉版本号后,就会报不兼容异常了,因为我们运行SerialTest序列化时类信息没变更之前的版本号是A,然后修改Serial类的版本号后,并修改了类的属性信息。再执行反序列话时发现读取的字节码信息中的序列号与当前类的版本号不同,所以会任务前后类型版本不一样,有变更,所以报运行时异常了。

    0 0
+ 订阅

时时分享云计算技术内容,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。

推荐文章