以下文章来源方志朋的博客,回复”666“获面试宝典

公司有个子服务较多,交互频繁的系统,有一些需要共享传输的对象,它们通过 JDK 序列化(Java Object Serialization)后进行交互;但是由于一些不可描述的历史原因,这些对象存在多个版本,每个版本中的属性不一致,且未设置 serialVersionUID

这阵子在做梳理/统一代码的工作,打算统一这些对象的版本和固定 serialVersionUID,但是由于服务较多,上线发版时会有一段新老版本共存的时期,所以得考虑这些对象序列化的兼容问题,新的对象反序列化一定得兼容老的对象

Java Object Serialization

Java对象序列化(Serialization)是指将Java中的对象转为字节流,从而可以方便的存储或在网络中传输,反序列化(Deserialization)是指将字节流转位Java对象

一般情况下,Java Object Serialization指的是利用JDK自带的功能对对象进行序列化/反序列化,而不是使用其他的序列化库进行(反)序列化

JDK 序列化中,要求对象必须实现java.io.Serializable接口,基本使用方式如下:

Serialization

// Serialize today's date to a file.
FileOutputStream f = new FileOutputStream("tmp");
ObjectOutput s = new ObjectOutputStream(f);
s.writeObject("Today");
s.writeObject(new Date());
s.flush();

Deserialization

// Deserialize a string and date from a file.
FileInputStream in = new FileInputStream("tmp");
ObjectInputStream s = new ObjectInputStream(in);
String today = (String)s.readObject();
Date date = (Date)s.readObject();

serialVersionUID

private static final long serialVersionUID = 1L;

Java Object Serialization 会使用对象中的 serialVersionUID 常量属性作为该对象的版本号,进行反序列化时会校验该版本号是否一致,如果不一致会导致序列化失败,抛出InvalidClassException异常

默认情况下,JVM 为每一个实现了 Serializable 的接口的类生成一个 serialVersionUID(long),这个 ID 的计算规则是通过当前类信息(类名、属性等)去生成的,所以当属性有变更时这个serialVersionUID 也一定会发生变更

这个 serialVersionUID 的生成,和所使用的JDK有关,不同的JDK可能会生成不一样的版本号,所以最好是手动生成一个,大多数 JAVA IDE 都会提供这个生成的功能

而且考虑到实际业务场景,变更属性是常有的事,如果使用自动生成的版本号很容易造成 serialVersionUID 不一致的问题,导致反序列化失败

serialVersionUID 不一致时的兼容处理

处理这个不一致也很简单,既然反序列化时使用 ObjectInputStream 来实现,那么这里自定义一个 CompatibleInputStream 继承 ObjectInputStream,然后重写 readClassDescriptor 方法即可

当遇到目标数据 Class 版本号和本地 Class 版本号不一致时,默认使用本地版本的 Class

public class CompatibleInputStream extends ObjectInputStream {private static Logger logger = LoggerFactory.getLogger(CompatibleInputStream.class);public CompatibleInputStream(InputStream in) throws IOException {super(in);}@Overrideprotected ObjectStreamClass readClassDescriptor() throws IOException, ClassNotFoundException {ObjectStreamClass resultClassDescriptor = super.readClassDescriptor(); // initially streams descriptorClass localClass; // the class in the local JVM that this descriptor represents.try {localClass = Class.forName(resultClassDescriptor.getName()); } catch (ClassNotFoundException e) {logger.error("No local class for " + resultClassDescriptor.getName(), e);return resultClassDescriptor;}ObjectStreamClass localClassDescriptor = ObjectStreamClass.lookup(localClass);if (localClassDescriptor != null) { // only if class implements serializablefinal long localSUID = localClassDescriptor.getSerialVersionUID();final long streamSUID = resultClassDescriptor.getSerialVersionUID();if (streamSUID != localSUID) { // check for serialVersionUID mismatch.final StringBuffer s = new StringBuffer("Overriding serialized class version mismatch: ");s.append("local serialVersionUID = ").append(localSUID);s.append(" stream serialVersionUID = ").append(streamSUID);Exception e = new InvalidClassException(s.toString());logger.error("Potentially Fatal Deserialization Operation.", e);resultClassDescriptor = localClassDescriptor; // Use local class descriptor for deserialization}}return resultClassDescriptor;}
}

以上关键代码摘自

https://stackoverflow.com/a/1816711/6507948

使用方式:

// Deserialize a string and date from a file.
FileInputStream in = new FileInputStream("tmp");
//反序列化时使用上面的CompatibleInputStream即可
ObjectInputStream s = new CompatibleInputStream(in);
String today = (String)s.readObject();
Date date = (Date)s.readObject();

来源 | https://juejin.cn/post/6961229793056686117

热门内容:拜访了这位小哥的GitHub后,我失眠了!
我们已经不用AOP做操作日志了!
强烈不建议你用 a.equals(b) 判断对象相等!
为什么强烈建议你不要做联表查询?没错,使用 Nacos 踩坑了
最近面试BAT,整理一份面试资料《Java面试BAT通关手册》,覆盖了Java核心技术、JVM、Java并发、SSM、微服务、数据库、数据结构等等。获取方式:点“在看”,关注公众号并回复 666 领取,更多内容陆续奉上。

明天见(。・ω・。)ノ♡

JDK 序列化, 碰到serialVersionUID 不一致问题,怎么处理?相关推荐

  1. Java序列化,碰到serialVersionUID不一致怎么处理?

    你知道的越多,不知道的就越多,业余的像一棵小草! 成功路上并不拥挤,因为坚持的人不多. 编辑:业余草 juejin.cn/post/6961229793056686117 推荐:https://www ...

  2. java 四字节uid,Java入门教程-序列化版本号serialVersionUID的作用

    原标题:Java入门教程-序列化版本号serialVersionUID的作用 Java序列化是将一个对象编码成一个字节流,反序列化将字节流编码转换成一个对象.序列化是Java中实现持久化存储的一种方法 ...

  3. java 序列化版本号_序列化版本号serialVersionUID的作用

    原标题:序列化版本号serialVersionUID的作用 Java序列化是将一个对象编码成一个字节流,反序列化将字节流编码转换成一个对象.序列化是Java中实现持久化存储的一种方法:为数据传输提供了 ...

  4. 序列化的 serialVersionUID 到底有什么用?

    作者:学无止境 来源:www.cnblogs.com/duanxz/p/3511695.html 实现Serializable接口的目的是为类可持久化,比如在网络传输或本地存储,为系统的分布和异构部署 ...

  5. java 序列化 uid_一文看懂Java序列化之serialVersionUID

    serialVersionUID适用于Java的序列化机制.简单来说,Java的序列化机制是通过判断类的serialVersionUID来验证版本一致性的.在进行反序列化时,JVM会把传来的字节流中的 ...

  6. Serializable序列化中serialVersionUId的作用

    Serializable是java所提供的一个序列化接口,它是一个空接口,为对象提供标准的序列化和反序列化操作,使用Serializable来实现序列化很简单,只要在类的声明中指定一个类似下面的标识即 ...

  7. Java序列化之serialVersionUID

    Java序列化之serialVersionUID 今天讲一讲Java对象中的serialVersionUID,先从序列化讲起. 什么是序列化 序列化,简单的说,就是将一个对象转化(编码)成可以传输的输 ...

  8. eclipse序列化生成serialVersionUID

    eclipse序列化生成serialVersionUID serialVersionUID作用: 序列化时为了保持版本的兼容性,即在版本升级时反序列化仍保持对象的唯一性. 如果你修改代码重新部署后出现 ...

  9. java jdk 序列化_JDK 11:Java序列化的终结开始了吗?

    java jdk 序列化 在博客文章" 将Google的协议缓冲区与Java结合使用 "中,我引用了乔什·布洛赫(Josh Bloch)的第三版的有效Java ,他写道:" ...

最新文章

  1. JSTL 读取数组 和 字符串连接
  2. 使用 FRP 反向代理实现 Windows 远程连接
  3. 让博客园的编辑器自动上传外链图片
  4. 辽宁学业水平测试 计算机考试,辽宁高中学业水平考试报名系统
  5. 动态规划训练9 [Brackets POJ - 2955 ]
  6. 【渝粤题库】陕西师范大学200481 高级英语(一)
  7. Java工作笔记-使用Maven创建多模块项目
  8. java改变实参_java中引用传递问题,在函数中修改引用的指向,会不会影响实参?...
  9. opencart笔记
  10. JSP教程第6讲笔记
  11. Python学习教程:爬虫分析了京东内衣销售记录,哪个size最多?
  12. ESP32 LVGL8.1 ——Label 标签 (Style 14)
  13. 关于在Google Earth中动态加载地标问题
  14. qpython3 l_QPython 3(com.hipipal.qpy3) - 3.0.0 - 应用 - 酷安网
  15. 用于科学计算机的计算器特点是什么意思,科学计算器在线e
  16. 仨人一起生活的日子刚刚好,不是吗?
  17. 乔春洋:品牌文化的三大内涵
  18. 递归-PTA循环日程表
  19. 微信小程序小白知识点bindtap()和this.setData({})
  20. Oracle数据库初学者:sql语句创建数据库表空间,建表语句

热门文章

  1. Social learning With Bayesian Agent and Random Decision Making
  2. document.onclick在ios上不触发的解决方法与touchstart点击穿透处理
  3. 微擎删除分类无法删除解决-select in效率低解决办法
  4. 我的C++笔记(数据的共享与保护)
  5. hdu1518 bjfuoj1042 zoj1909 poj2362 经典的搜索加剪枝
  6. 【青少年编程竞赛交流】01月份微信图文索引
  7. 【青少年编程】【三级】打气球游戏
  8. 【青少年编程】全国青少年软件编程等级考试大纲与说明(Scratch)
  9. LeetCode实战:螺旋矩阵 II
  10. LeetCode实战:螺旋矩阵