1. serialVersionUID 问题


前段时间正好也遇到了serialVersionUID  问题, 系统升级后,发现部分App终端办理部分业务的时候会出现系统InvalidClassException报错(如下图),从报错内容看问题是由于serialVersionUID引起

分析这个问题,可以从系统日志中找到到报错对应的堆栈信息,从报错日志看ObjectStreamClass#initNonProxy处理时抛出异常InvalidClassException 。

Exception in thread "main" java.io.InvalidClassException: com.star.sms.service.accept2.dto.purchase.ResourceDTO; local class incompatible: stream classdesc serialVersionUID = -4455611054423873003, local class serialVersionUID = 7061157640146872190at java.io.ObjectStreamClass.initNonProxy(ObjectStreamClass.java:616)at java.io.ObjectInputStream.readNonProxyDesc(ObjectInputStream.java:1630)at java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1521)at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1781)at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1353)at java.io.ObjectInputStream.readObject(ObjectInputStream.java:373)at serialization.Reader.main(Reader.java:16)

要了解报错具体原因还需要查看java.io.ObjectStreamClass的源码,从源码看,ObjectInputSteam流对象读取数据个过程中,  程序会做serialVersionUID对比,对比时发现了serialVersionUID值不同,所以抛出了异常, 并在异常中记录了读取的对象信息和serialVersionUID 值,

//查看java.io.ObjectStreamClass源码if (serializable == localDesc.serializable &&!cl.isArray() &&suid.longValue() != localDesc.getSerialVersionUID()){throw new InvalidClassException(localDesc.name, "local class incompatible: " +"stream classdesc serialVersionUID = " + suid +", local class serialVersionUID = " +localDesc.getSerialVersionUID());
}

上面抛错的原因就是ResourceDTO对象读取存在问题,查看ResourceDTO发现对象中并没有显示定义serialVersionUID,那么serialVersionUID的值如何来的呢, 并且serialVersionUID有什么作用呢?

public class ResourceDTO implements Serializable {private Long resourceId;private Long resourceTypeId;//略
}

2.什么是序列化


了解serialVersionUID 之前,需要先理解什么是序列化

在创建数据对象的时候,我们经常会让对象实现java.io.Serializable接口,Serializable接口是启用其序列化功能的接口。实现java.io.Serializable 接口的类是可序列化的。没有实现此接口的类将不能使它们的任意状态被序列化或逆序列化,

java.io.Serializable接口没有任何实现,一般我们把这类接口叫做标识接口

package java.io;public interface Serializable {
}

为什么要序列化呢?

序列化是指把java对象转换为字节序列的过程,反序列化是指把字节序列恢复为java对象的过程。 任何类型只要实现了Serializable接口,就可以被保存到文件中,或者作为数据流通过网络发送到别的地方。也可以用管道来传输到系统的其他程序中。 由此可见序列化操作的重要性。


3. serialVersionUID 作用


当Java对象做序列化和反序列化操作的时候,需要验证版本一致性。serialversionuid的作用是标识版本,主要用于程序的版本控制;如果serialversionuid一致,说明他们的版本是一样的;反之就说明版本不同, 比如当我们进行序列化操作一个对象,会把当前的版本serialversionuid写入到文件之中。在运行的时候,它就会监测当前版本的serialversionuid与编写版本是否一致。

Java对象实现java.io.Serializable接口后,可以定义serialVersionUID  也可以不定义serialVersionUID

public class ResourceDTO implements Serializable {//定义serialVersionUIDprivate static final long serialVersionUID = -4455611054423873003L;private Long resourceId;private Long resourceTypeId;//略
}

当不定义 时,一般开发工具会有黄色波浪线警告,内容为“The serializable class  类名 does not declare a static final serialVersionUID field of type long”

如果没有定义一个名为serialVersionUID,类型为long的变量,Java序列化机制会根据编译的class自动生成一个serialVersionUID,即隐式声明。默认的serialVersionUID计算时,对类详细信息高度敏感(类名、接口名、成员方法及属性等),并且这些详细信息可能因编译器而异。因此只有同一次编译生成的class才会生成相同的serialVersionUID 。此时如果对某个类进行修改的话,那么版本上面是不兼容的,就会出现反序列化报错问题。


4.文章总结


当理解了serialVersionUID作用后, 上文中提到的系统报错问题原因就十分明显了, ResourceDTO 对象没有声明serialVersionUID。 因此在程序中存在的ResourceDTO对象并非是同一次编译的对象。不同对象造成了反序列化报错,  也正是按照这个思路分析系统最终发现,系统中补丁部署存在问题。

当保证系统中只有一个版本的ResourceDTO 对象问题就可解决,或者显示声明serialVersionUID,即使有不同版本ResourceDTO,保证serialVersionUID相同也可以避免上问题提到的InvalidClassException报错, 所以开发的时候也将常设置serialVersionUID = 1L

public class ResourceDTO implements Serializable {private static final long serialVersionUID = 1L;private Long resourceId;private Long resourceTypeId;//略
}

上一篇:JVM记一次CPU飙升

Java中serialVersionUID作用相关推荐

  1. Java中接口作用的理解

    关于Java中接口作用的深入理解.这是个很容易遇到的问题吧,看下面红色的部分应该就能理解了.要把接口视作一种共同规范. / 2019/3/1 补充 : 接口的存在也是为了弥补类无法多继承的缺点,假设一 ...

  2. java类中serialversionuid 作用 是什么?举个例子说明

    转自https://www.cnblogs.com/duanxz/p/3511695.html serialVersionUID适用于Java的序列化机制.简单来说,Java的序列化机制是通过判断类的 ...

  3. java中ioc作用_Spring中的IOC是什么意思,为什么要用IOC而不是New来创建实例?

    这里是修真院后端小课堂,每篇分享文从 [背景介绍][知识剖析][常见问题][解决方案][编码实战][扩展思考][更多讨论][参考文献] 八个方面深度解析后端知识/技能,本篇分享的是: [Spring中 ...

  4. Java中@Deprecated作用、使用以及引用

    一.作用 在Java中凡是使用@Deprecated标志的类,都是不鼓励使用的类,如果使用或者进行重写,程序会发出警告. 二.场景 一般的话,使用这个注释都是该类不再使用,比如说设计类的时候,之前类存 ...

  5. Java中包装类作用及注意点

    Java中对每种基本类型都有一个对应的包装类,这里主要讲解包装类的作用和包装类使用时的一些注意点. 包装类的作用 作用主要有以下两方面: - 编码过程中只接收对象的情况,比如List中只能存入对象,不 ...

  6. java中ioc作用_java中的ioc是什么

    java中的ioc是什么 发布时间:2020-06-03 20:01:10 来源:亿速云 阅读:174 作者:Leah java中的ioc是什么相信大部分人都不太了解,为了让大家更加了解,小编给大家总 ...

  7. java中properties作用,java中Properties类的使用

    java中Properties类的使用 在java.util 包下面有一个类 Properties,该类主要用于读取以项目的配置文件(以.properties结尾的文件和xml文件). Propert ...

  8. java中properties作用,Java中Properties的使用详解

    Java中有个比较重要的类Properties(Java.util.Properties),主要用于读取Java的配置文件,各种语言都有自己所支 持的配置文件,配置文件中很多变量是经常改变的,这样做也 ...

  9. java中 jacob作用_【JAVA】JACOB使用简介

    它允许在java中调用com接口自动组件,它使用JNI(本地调用程序)来进行本地调用COM库.它可运行在x86和支持32位和64位Java虚拟机 X64的环境. 测试源码包: 密码: ej9u JAC ...

  10. 面试官:Java中 serialVersionUID 的作用是什么?举个例子说明

    点击上方蓝色"方志朋",选择"设为星标" 回复"666"获取独家整理的学习资料!来源:blog.csdn.net/andy_zhang200 ...

最新文章

  1. 一次win10体验旅程
  2. 模4余1的素数一定能表示为两正整数的平方和
  3. 安全研究剖析:******方式演示
  4. 【bzoj3160】万径人踪灭
  5. python单元测试mock_python3的单元测试模块mock与性能测试模块cProfile
  6. 关于java中next,nextInt,nextLine的区别
  7. 构建一套高逼格 Nginx 集群监控系统!
  8. python爬虫有几种方法_python爬虫-----Python访问http的几种方式
  9. Git之Github使用(一):Push代码到Github
  10. C++17特性一览(转载)
  11. mysql面试必会6题经典_经典sql面试题及答案第7期
  12. Monte Carlo Algorithms
  13. 怎么有效的管理微信群?分享3点有用的经验
  14. php怎么更换图片背景的软件,照片换背景颜色 照片换背景用什么软件|教你怎么换照片背景颜色...
  15. Vue项目 chrome页面崩溃:喔唷 崩溃了, 并出现警告Forced reflow while executing JavaScript took Nms
  16. 计算广告:第一章——在线广告综述
  17. python首字母大写
  18. 众多mock工具,这一次我选对了
  19. 龚鹏:我是怎么从程序员成为全栈GEEK的
  20. Davinci的异构多核间通信基础组件SysLink

热门文章

  1. android自定义速度仪表盘,自定义View实战:汽车速度仪表盘
  2. Android实现自定义曲线截屏,Android实现矩形区域截屏的方法
  3. 调用Windows远程桌面应用
  4. fences(桌面整理软件)与eDiary3.3.3下载链接
  5. lopatkin俄大神精简Windows 10 Pro 19041.450 20H1 Release x86-x64 ZH_CN DREY[2020-08-19]
  6. 【转】概要设计文档编写规范
  7. 【通俗易懂系列】深度可分离卷积
  8. 先写接口文档还是先开发
  9. 960H 、SDI和百万高清,谁会率先出局?
  10. 把B站表情包植入MATLAB