一次线上升级大规模报错后,我又重新学习了序列化!

软件发布|下载排行|最新软件

当前位置:首页IT学院IT技术

一次线上升级大规模报错后,我又重新学习了序列化!

Java碎碎念   2020-03-31 我要评论
### 背景 去年9月份时候fastjson出现过一个漏洞,需要升级到1.2.60,旧版本是1.2.12,测试环境验证完毕后上线,上线几分钟瞬间几百封报错邮件,当时瞬间心里特紧张,但是表面上得装着没事,咱能搞定,哈哈,还好迅速定位并解决了问题。 ### 系统流程 出问题模块流程比较简单,需要查询一些数据,先从Redis查询,没有再查询数据库并把结果放到Redis中缓存。 ### 问题排查 报错异常信息如下: ``` java.io.InvalidClassException: com.alibaba.fastjson.JSONObject; local class incompatible: stream classdesc serialVersionUID = -7894253080042154647, local class serialVersionUID = 1 ``` 看到报错可能你已经明白了,反序列化时候版本不一致导致的问题,那么问题是如何产生的呢? Fastjson1.2.60源码的JSONObject类里有下面一行代码: ``` private static final long serialVersionUID = 1L; ``` 而1.2.12版本源码的JSONObject类里没有定义serialVersionUID。 Java的序列化机制是通过判断类的serialVersionUID来验证版本一致性的,在进行反序列化时,JVM会把传来的字节流中的serialVersionUID与本地相应实体类的serialVersionUID进行比较,如果相同就认为是一致的,可以进行反序列化,否则就会出现序列化版本不一致的异常 当实现java.io.Serializable接口的类没有显式地定义一个serialVersionUID变量时候,Java序列化机制会根据编译的Class自动生成一个serialVersionUID作序列化版本比较用,这种情况下,如果Class文件(类名,方法明等)没有发生变化(增加空格,换行,增加注释等等),就算再编译多次,serialVersionUID也不会变化的。 问题原因找到了,系统返回实体里存放了JSONObject的对象,系统上线后用户访问时候如果缓存有数据,就会出现反序列化版本不一致的情况,导致出现异常。 ### 解决方案 先说下我的方案,使用新版本的jar包,把设置缓存代码里key的前缀修改下,这样就不会使用旧的缓存进行反序列化,问题解决。 例如: ``` //原始代码 @CacheEvict(value="RedisCache11",key="'user:test:'+#obj.id",beforeInvocation=true) //修改后代码 @CacheEvict(value="RedisCache11",key="'user:test2020:'+#obj.id",beforeInvocation=true) ``` 以上是我的一种的解决方案,如果你有其他的方案,欢迎留言沟通哦! **推荐阅读** [1.记一次线上Mysql慢查询排查经历!](https://mp.weixin.qq.com/s/fp708jy0_HBP7MChEf-4XA) [2.彻底理解cookie、session、token](https://mp.weixin.qq.com/s/AVwanj-benepE_AvYelHIg) [3.阿里面试官:分别说说微信和淘宝扫码登录背后的实现原理?](https://mp.weixin.qq.com/s/cOdk9ofelda6npzvk8F1Vg) [4.一分钟带你了解下MyBatis的动态SQL!](https://mp.weixin.qq.com/s/FRvQeLgPY1Md1K2G3naK0Q) [5.原创 | 我是如何解决POI解析Excel出现的OOM问题的?](https://mp.weixin.qq.com/s/97UDUci8u8A3KNi7-xw9eQ) *** >如果觉得文章不错,希望可以随手转发或者”在看“哦,非常感谢哈! >关注下方公众号后回复「1024」,有惊喜哦! ![](https://img2018.cnblogs.com/blog/463242/202001/463242-20200116154914338-370772914.png)

Copyright 2022 版权所有 软件发布 访问手机版

声明:所有软件和文章来自软件开发商或者作者 如有异议 请与本站联系 联系我们