技术分享 JAVA基础 查看内容

对象序列化与反序列化 InvalidClassException

老高 | 发布于 2021-03-17 13:41| 浏览()| 评论() | 收藏() | 点赞() | 打印

摘要: 没有默认serialVersionUID ,在生产环境反序列化失败,但是测试环境无论怎样都不会有问题,引用了相同的jar包,但是serialVersionUID 不是在编译时指定,而是在运行时根据该类生成,所以即使引用相同的jar包最后的序列号也可能不一样

InvalidClassException异常处理

在生产环境遇见以下错误

java.lang.IllegalArgumentException: Failed to deserialize object
        at org.springframework.util.SerializationUtils.deserialize(SerializationUtils.java:68)
        at com.sf.ccsp.inter.redis.RedisTemplate.getSerialization(RedisTemplate.java:2538)
        at com.sf.ccsp.inter.service.PLDKafkaMessageService.getCityName(PLDKafkaMessageService.java:368)
        at com.sf.ccsp.inter.service.PLDKafkaMessageService.coverToWaybillTO(PLDKafkaMessageService.java:105)
        at com.sf.ccsp.inter.service.PLDKafkaMessageService.handle(PLDKafkaMessageService.java:77)
        at com.sf.ccsp.inter.listener.FvpPldListener.onMessage(FvpPldListener.java:58)
        at com.sf.kafka.api.consume.KafkaConsumer$ConsumeTask.run(KafkaConsumer.java:230)
        at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:471)
        at java.util.concurrent.FutureTask.run(FutureTask.java:262)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
        at java.lang.Thread.run(Thread.java:745)
Caused by: java.io.InvalidClassException: com.sf.ccsp.basic.client.response.AddressResp; local class incompatible: stream c
lassdesc serialVersionUID = 8651924817573918117, local class serialVersionUID = -7189267544850088870
        at java.io.ObjectStreamClass.initNonProxy(ObjectStreamClass.java:617)
        at java.io.ObjectInputStream.readNonProxyDesc(ObjectInputStream.java:1622)
        at java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1517)
        at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1771)
        at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1350)
        at java.io.ObjectInputStream.readObject(ObjectInputStream.java:370)
        at org.springframework.util.SerializationUtils.deserialize(SerializationUtils.java:65)
        ... 11 more

原因:

没有默认serialVersionUID ,在生产环境反序列化失败,但是测试环境无论怎样都不会有问题,引用了相同的jar包,但是serialVersionUID 不是在编译时指定,而是在运行时根据该类生成,所以即使引用相同的jar包最后的序列号也可能不一样

无论eclipse还是idea(默认关闭序列化提示,需手动打开),都可以自动生成相应的序列号,分为两类1L,XXXL。

private static final long serialVersionUID = 1L;
private static final long serialVersionUID = 3617859655330969141L;

当然如果不指定,系统也会自动生成,但是存在隐性风险 ,不同的编译器对同一个对象可能生成相同的序列号,也可能生成不同的序列号

java serialVersionUID在运行时基于该类的各个方面计算该类的默认 serialVersionUID 值,记住是运行时,所以哪怕是引用相同的jar包,最后的序列号也可能相同可能不同。

在指定序列化值后,即使在后来的对象中添加了字段(没有删除与修改),序列化值是此前的,只要保证反序列化对象和最新的保持一致均能正常反序列化。

子类序列化与父类序列化(Serializable)的区别

1. 如果子类实现Serializable接口而父类未实现时,父类不会被序列化!

2. 如果父类实现序列化,子类自动实现序列化,不需要显式实现Serializable接口。

原因:这个就跟子类/父类的内存分配有关系了,具体可看如下博文:

http://blog.csdn.net/smithdoudou88/article/details/12756187

http://blog.csdn.net/u011386422/article/details/42582605


发表评论(对文章涉及的知识点还有疑问,可以在这里留言,老高看到后会及时回复的。)

表情