Java中serialVersionUID作用

Java中serialVersionUID作用聊聊序列化接口 java io Serializable 和 serialVersio

Java中serialVersionUID作用


1. serialVersionUID 问题


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

Java中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 = -, local class serialVersionUID =  at 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 { //定义serialVersionUID private static final long serialVersionUID = -L; 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飙升

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/176505.html原文链接:https://javaforall.net

(0)
上一篇 2026年3月26日 下午9:46
下一篇 2026年3月26日 下午9:46


相关推荐

  • IaaS、PaaS和SaaS的区别

    IaaS、PaaS和SaaS的区别IaaS PaaS 和 SaaS 到底是什么 本文就用最通俗的语言来说透 这些高大上的概念到底是什么 云服务 现在已经快成了一个家喻户晓的词了 如果你不知道 PaaS IaaS 和 SaaS 的区别 那么也没啥 因为很多人确实不知道 云 其实是互联网的一个隐喻 云计算 其实就是使用互联网来接入存储或者运行在远程服务器端的应用 数据 或者服务 任何一个使用基于互联网的方法任何一个使用基于互

    2026年3月19日
    2
  • Java中遍历Map集合的五种方式[通俗易懂]

    包含for循环遍历、entrySet使用iterator遍历,并且介绍了Java8新特性使用lambda表达式forEach遍历。

    2022年4月9日
    65
  • 一点就分享系列(实践篇3-上篇)— 修改YOLOV5 之”魔刀小试“+ Trick心得分享+V5精髓部分源码解读

    一点就分享系列(实践篇3-上篇)— 修改YOLOV5 之”魔刀小试“+ Trick心得分享+V5精髓部分源码解读一点就分享系列(实践篇3—上篇)—“全网首发”正确手法修改YOLOV5魔刀小试+Trick心得分享现在部署大热,而我觉得回归原理和源码更加重要!在检测领域YOLOV5肯定是大家的炼丹必备模型,收敛快,精度高都是其爱不释手的理由,各种魔改基础backone或者别的trcik也层出不穷,这里我自己针对V5的head添加了ASFF自适应的特征融合检测层,分享下,也顺手告诉大家如何以正规的手法去修改YOLOV5的网络结构!文章目录一点就分享系列(实践篇3—上篇)—“全网首发”正确手法修改YOLOV5

    2022年5月23日
    42
  • c语言错误lnk1120_2019咬文嚼字十大错误

    c语言错误lnk1120_2019咬文嚼字十大错误错误提示LNK2019错误,其实早找我之前就遇到过:C++BookNote-LNK2019严重性 代码 说明 项目 文件 行 禁止显示状态错误 LNK2019 无法解析的外部符号“public:__thiscallmy_util::ReferCounter::ReferCounter(void)”(??0?KaTeXparseerror:Expectedgroupafter’_’atposition71:…c:staticvoid_̲_cdeclmy

    2022年10月5日
    5
  • pycharm的激活码_通用破解码

    pycharm的激活码_通用破解码,https://javaforall.net/100143.html。详细ieda激活码不妨到全栈程序员必看教程网一起来了解一下吧!

    2022年3月16日
    68
  • 安卓—项目中插入百度地图sdk

    安卓—项目中插入百度地图sdk

    2022年1月19日
    58

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号