[已解决]报异常java.io.InvalidClassException的解决方法|对象序列化实现Serializable会出现java.io.InvalidClassException的异常

简介: [已解决]报异常java.io.InvalidClassException的解决方法|对象序列化实现Serializable会出现java.io.InvalidClassException的异常

一、前言

今天在增加完新功能后, 部署的时候,突然就遇到了java.io.InvalidClassException的问题,这些都是我们平常不注意细节造成的后果。

具体异常如下

分析异常:Caused by:java. io. InvalidClassException: com. eastcom xxx.xxxxxx. bean. AlarmReq; local class incompatible: stream classdesc serialversionUID =1631280650588763177, local class seriaiversionuId = 6638111461888145730


二、分析原因

首先我们的系统架构,是因为要将对象通过

AlarmReq alarmReq= JSONObject.toJavaObject(json,AlarmReq.class);
redisQueue = redisTaskContainer.getRedisQueue();
redisQueue.pushFromHead(alarmReq);

上述方法会将对象序列化到redis内存中,然后又再通过 redisTemplate.getValueSerializer().deserialize() 方法将数据反序列化到bean对象,这样的话,如果改动了这个bean对象的话,即加了属性的话,就会导致serialVersionUID会变,而且当时我们的bean对象即上述的AlarmReq对象,当时是没有加serialVersionUID的。


由于序列化时该类的serialVersionUID是JVM根据类名及其属性的哈希值生成的。当类的属性有变动时,serialVersionUID也会相应变动,从而导致redis中的老数据反序列化为AlarmReq bean对象时,serialVersionUID匹配不上而失败,会报出java. io. InvalidClassException。


 

三、解决问题

知道原因了,我们就可以解决问题了


方法1:不考虑和老数据兼容的话,直接在你实现了Serializable的这个对象加一段serialVersionUID代码,如果还报InvalidClassException,将redis上的老数据清除


private static final long serialVersionUID = 1L;

方法2:兼容老数据,找到老数据的serialVersionUID,就是上述报错的地方,会将老数据的serialVersionUID报出来,比如我这里的老数据的就是1631280650588763177 这一串,你只要加 UID=1631280650588763177 这个就可以了。

private static final long serialVersionUID = 1631280650588763177L;



四、总结

可能好多人在写对象以及序列化对象的时候,是没有加private static final long serialVersionUID的,但是也没有见到有报InvalidClassException异常的,那是因为你部署的单体系统架构,实时序列化和反序列化的,每次系统重启就又重新实例对象,所以即使改变了对象增加属性,也不会出现老对象和新对象serialVersionUID 不一致的情况,所以也就不会出现java. io. InvalidClassException。


所以以后你们写对象并且要序列化的话,一定要随手加上serialVersionUID这段代码。


如果你们去看源码,HashMap、ArrayList 等这些神级代码的时候,你们可以看到,他们都是加了 serialVersionUID 代码的


 

五、使用idea工具自动生成

1、按照下图所示,设置好后,不要忘记点击【Apply】应用一下

 

2、在实现了 Serializable的bean类下, 鼠标移到bean类名处,按住 alt+enter,就会自动弹出【Add serialVersionUID field】

选中即可自动生成啦,

相关文章
|
5月前
|
设计模式 网络协议 数据可视化
Java 设计模式之状态模式:让对象的行为随状态优雅变化
状态模式通过封装对象的状态,使行为随状态变化而改变。以订单为例,将待支付、已支付等状态独立成类,消除冗长条件判断,提升代码可维护性与扩展性,适用于状态多、转换复杂的场景。
805 157
|
5月前
|
Java Unix Go
【Java】(8)Stream流、文件File相关操作,IO的含义与运用
Java 为 I/O 提供了强大的而灵活的支持,使其更广泛地应用到文件传输和网络编程中。!但本节讲述最基本的和流与 I/O 相关的功能。我们将通过一个个例子来学习这些功能。
259 1
|
7月前
|
Java 测试技术 API
Java IO流(二):文件操作与NIO入门
本文详解Java NIO与传统IO的区别与优势,涵盖Path、Files类、Channel、Buffer、Selector等核心概念,深入讲解文件操作、目录遍历、NIO实战及性能优化技巧,适合处理大文件与高并发场景,助力高效IO编程与面试准备。
|
7月前
|
缓存 安全 Java
Java反射机制:动态操作类与对象
Java反射机制是运行时动态操作类与对象的强大工具,支持获取类信息、动态创建实例、调用方法、访问字段等。它在框架开发、依赖注入、动态代理等方面有广泛应用,但也存在性能开销和安全风险。本文详解反射核心API、实战案例及性能优化策略,助你掌握Java动态编程精髓。
|
8月前
|
存储 Java Linux
操作系统层面视角下 Java IO 的演进路径及核心技术变革解析
本文从操作系统层面深入解析Java IO的演进历程,涵盖BIO、NIO、多路复用器及Netty等核心技术。分析各阶段IO模型的原理、优缺点及系统调用机制,探讨Java如何通过底层优化提升并发性能与数据处理效率,全面呈现IO技术的变革路径与发展趋势。
188 2
|
7月前
|
SQL Java 数据库连接
Java IO流(一):字节流与字符流基础
本文全面解析Java IO流,涵盖字节流、字符流及其使用场景,帮助开发者理解IO流分类与用途,掌握文件读写、编码转换、异常处理等核心技术,通过实战案例提升IO编程能力。
|
7月前
|
存储 人工智能 JavaScript
Java从作用域到对象高级应用​
本内容详细讲解了JavaScript中的作用域类型(函数作用域、块作用域、全局作用域)、作用域链、垃圾回收机制、闭包、变量提升、函数参数、数组方法、内置构造函数、对象高级知识、原型链、对象赋值、深浅拷贝、递归、异常处理及this指向等内容,全面覆盖JS核心概念与编程技巧。
92 0
|
5月前
|
JSON 网络协议 安全
【Java】(10)进程与线程的关系、Tread类;讲解基本线程安全、网络编程内容;JSON序列化与反序列化
几乎所有的操作系统都支持进程的概念,进程是处于运行过程中的程序,并且具有一定的独立功能,进程是系统进行资源分配和调度的一个独立单位一般而言,进程包含如下三个特征。独立性动态性并发性。
290 1
|
5月前
|
JSON 网络协议 安全
【Java基础】(1)进程与线程的关系、Tread类;讲解基本线程安全、网络编程内容;JSON序列化与反序列化
几乎所有的操作系统都支持进程的概念,进程是处于运行过程中的程序,并且具有一定的独立功能,进程是系统进行资源分配和调度的一个独立单位一般而言,进程包含如下三个特征。独立性动态性并发性。
311 1
|
9月前
|
存储 Java 编译器
说一说关于序列化/反序列化中的细节问题
我是小假 期待与你的下一次相遇 ~
180 1