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

本文涉及的产品
Redis 开源版,标准版 2GB
推荐场景:
搭建游戏排行榜
云数据库 Tair(兼容Redis),内存型 2GB
简介: [已解决]报异常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】

选中即可自动生成啦,

相关实践学习
基于Redis实现在线游戏积分排行榜
本场景将介绍如何基于Redis数据库实现在线游戏中的游戏玩家积分排行榜功能。
云数据库 Redis 版使用教程
云数据库Redis版是兼容Redis协议标准的、提供持久化的内存数据库服务,基于高可靠双机热备架构及可无缝扩展的集群架构,满足高读写性能场景及容量需弹性变配的业务需求。 产品详情:https://www.aliyun.com/product/kvstore     ------------------------------------------------------------------------- 阿里云数据库体验:数据库上云实战 开发者云会免费提供一台带自建MySQL的源数据库 ECS 实例和一台目标数据库 RDS实例。跟着指引,您可以一步步实现将ECS自建数据库迁移到目标数据库RDS。 点击下方链接,领取免费ECS&RDS资源,30分钟完成数据库上云实战!https://developer.aliyun.com/adc/scenario/51eefbd1894e42f6bb9acacadd3f9121?spm=a2c6h.13788135.J_3257954370.9.4ba85f24utseFl
相关文章
|
17天前
|
安全 Java 编译器
Java对象一定分配在堆上吗?
本文探讨了Java对象的内存分配问题,重点介绍了JVM的逃逸分析技术及其优化策略。逃逸分析能判断对象是否会在作用域外被访问,从而决定对象是否需要分配到堆上。文章详细讲解了栈上分配、标量替换和同步消除三种优化策略,并通过示例代码说明了这些技术的应用场景。
Java对象一定分配在堆上吗?
|
21天前
|
Java API
Java 对象释放与 finalize 方法
关于 Java 对象释放的疑惑解答,以及 finalize 方法的相关知识。
42 17
|
21天前
|
存储 安全 Java
Java编程中的对象序列化与反序列化
【10月更文挑战第22天】在Java的世界里,对象序列化和反序列化是数据持久化和网络传输的关键技术。本文将带你了解如何在Java中实现对象的序列化与反序列化,并探讨其背后的原理。通过实际代码示例,我们将一步步展示如何将复杂数据结构转换为字节流,以及如何将这些字节流还原为Java对象。文章还将讨论在使用序列化时应注意的安全性问题,以确保你的应用程序既高效又安全。
|
20天前
|
存储 缓存 NoSQL
一篇搞懂!Java对象序列化与反序列化的底层逻辑
本文介绍了Java中的序列化与反序列化,包括基本概念、应用场景、实现方式及注意事项。序列化是将对象转换为字节流,便于存储和传输;反序列化则是将字节流还原为对象。文中详细讲解了实现序列化的步骤,以及常见的反序列化失败原因和最佳实践。通过实例和代码示例,帮助读者更好地理解和应用这一重要技术。
19 0
Java基础异常-自定义异常
Java基础异常-自定义异常
Java基础异常-自定义异常
|
Java 编译器
Java中的异常(抛出异常、自定义异常等)
Java中的异常(抛出异常、自定义异常等)
303 1
|
Java 程序员 编译器
Java异常——throw、throws及自定义异常
Java异常——throw、throws及自定义异常
128 0
|
存储 Java 编译器
【Java】认识异常及自定义异常
【Java】认识异常及自定义异常
【Java】认识异常及自定义异常