项目场景:
第一次进入获取员工信息的方法时,会先通过序列化数据库的对应员工信息并保存到 Redis 中。
第二次进入获取员工信息的方法时,直接取出 Redis 里序列化后员工信息,进行反序列化后返回。
问题描述
这里是第一次保存成功后,第二次反序列化的时候,一直提示反序列化某个字符异常。
这里我写了一个对应的简单测试
功能:
- 获取对应的序列化工具包
- 通过工具包序列化 User 对象为字节
- 通过工具包把字节转换成 User 对象
其中 FstSerializer 是一个对应的序列化类
public static void main(String[] args) throws Exception {
FstSerializer instance = FstSerializer.getInstance();
// 由于业务数据需要保密,这里可以理解为一个user对象的Json串
String jsonS = "{\"userId\":1,\"userNamel\":zs\",\"amount\":2.00......\"\"}";
User user= JsonUtil.str2Object(jsonS, User.class);
byte[] serialize = instance.serialize(user);
User deserialize = instance.deserialize(serialize, User.class);
System.out.println(deserialize.getUserId());
}
运行时候会抛出解析某个字节异常 (细心的话可以发现有一个BigDecimal 的报错)
原因分析:
- 一开始的第一想法是从 unknown object tag -126 入手,但是在网上找了好久没有对应的解决方案。
- 接着考虑到序列化的工具包是我们公司自己封装的,会不会是工具包解析有异常呢。
(自己在那 debug 了半天,没发现什么问题) - 接着又想到让同事跑一下相同的代码,看一下有什么问题吗。
(诡异的事情发生了,他的电脑是可以正常反序列出来的) - 这时候,我已经有点郁闷了。别人不出问题,就我有问题。
(那环境或者对应的版本号有问题吗)
看了许久,对了项目仓库版本号啥的,一切都是一致的。
最后又反回去看了一下报错(重要的遗漏点 ===> 一开始以为Jdk 的类能有什么好看的呢): at java.math.BigDecimal.readObject(BigDecimal.java:3798)
最后,大哥给了我一个大胆的猜想:会不会是 JDK 版本有 bug 呢
我对了一下我们两个机器的 jdk 版本号。
我的机器: 1.8.0_351
同事的机器: 1.8.0_301
然后我们对比了两个人 BigDecimal 类中的 readObject 方法
1.8.0_351 (报错的那一行)
1.8.0_301 (正常运行版本中的方法)
解决方案:
底层代码我也没有去深究了,我把 jdk 的版本降为 1.8.0_301。重新运行后,它可以正常反序列化,并拿到对应的 userId。
升级后,可能是对 BigDecimal 读取属性值没有做兼容。导致反序列化的时候,出了异常;只能说这种情况还是十分低的。如果遇到同样的问题,希望对你有所帮助。