`
zsw_sh
  • 浏览: 13309 次
文章分类
社区版块
存档分类
最新评论

serialVersionUID介绍与作用

 
阅读更多
Java的序列化机制是通过在运行时判断类的serialVersionUID来验证版本一致性的。在进行反序列化时,JVM会把传来的字节流中的serialVersionUID与本地相应实体(类)的serialVersionUID进行比较,如果相同就认为是一致的,可以进行反序列化,否则就会出现序列化版本不一致的异常。

Eclipse中The serializable class XXXXXX does not declare a static final serialVersionUID field of type long出现这样的警告处理办法。

当采用程序的Add default Serial version ID修复时,Eclipse会加上:private static final long serialVersionUID = 1L;

当采用程序的Add generated Serial version ID修复时,Eclipse会加上:private static final long serialVersionUID = xxxxL;

其实这个问题出现的具体原因是和序列化中的这个serialVersionUID有关。

serialVersionUID 用来表明类的不同版本间的兼容性。有两种生成方式:

一个是默认的1L,比如:private static final long serialVersionUID = 1L;(对应修复方法1)

一个是根据类名、接口名、成员方法及属性等来生成一个64位的哈希字段,比如:
private static final long serialVersionUID = xxxxL;(对应修复方法2)

在JDK中,可以利用JDK的bin目录下的serialver.exe工具产生这个serialVersionUID 的值,对于Test.class,执行命令:
serialver Test 这时JVM(java虚拟机)会生成一个哈希字段。

对比一下这个哈希字段的值与方法2中生成的字段值是一样的,可见,在CMD中使用serialver指令就是根据类名、接口名、成员方法及属性等来生成哈希字段的。

下面来讨论java类中为什么需要重载 serialVersionUID 属性。

当两个进程在进行远程通信时,彼此可以发送各种类型的数据。无论是何种类型的数据,都会以二进制序列的形式在网络上传送。发送方需要把这个Java对象转换为字节序列,才能在网络上传送;接收方则需要把字节序列再恢复为Java对象。

  把Java对象转换为字节序列的过程称为对象的序列化。

  把字节序列恢复为Java对象的过程称为对象的反序列化。

  对象的序列化主要有两种用途:

  1) 把对象的字节序列永久地保存到硬盘上,通常存放在一个文件中;

  2) 在网络上传送对象的字节序列。

java.io.ObjectOutputStream代表对象输出流,它的writeObject(Object obj)方法可对参数指定的obj对象进行序列化,把得到的字节序列写到一个目标输出流中。

java.io.ObjectInputStream代表对象输入流,它的readObject()方法从一个源输入流中读取字节序列,再把它们反序列化为一个对象,并将其返回。

只有实现了Serializable和Externalizable接口的类的对象才能被序列化。Externalizable接口继承自Serializable接口,实现Externalizable接口的类完全由自身来控制序列化的行为,而仅实现Serializable接口的类可以采用默认的序列化方式 。

凡是实现Serializable接口的类都有一个表示序列化版本标识符的静态变量:private static final long serialVersionUID;

类的serialVersionUID的默认值完全依赖于Java编译器的实现,对于同一个类,用不同的Java编译器编译,有可能会导致不同的serialVersionUID,也有可能相同。为了提高serialVersionUID的独立性和确定性,强烈建议在一个可序列化类中显示的定义serialVersionUID,为它赋予明确的值。显式地定义serialVersionUID有两种用途:

  1)在某些场合,希望类的不同版本对序列化兼容,因此需要确保类的不同版本具有相同的serialVersionUID;在某些场合,不希望类的不同版本对序列化兼容,因此需要确保类的不同版本具有不同的serialVersionUID。

  2)当你序列化了一个类实例后,希望更改一个字段或添加一个字段,不设置serialVersionUID,所做的任何更改都将导致无法反序化旧有实例,并在反序列化时抛出一个异常。如果你添加了serialVersionUID,在反序列旧有实例时,新添加或更改的字段值将设为初始化值(对象为null,基本类型为相应的初始默认值),字段被删除将不设置。

当系统不需要序列化类时,可以去掉这些警告,做如下设置:Window-->Preferences-->Java,将serializable class without serialVersionUID的设置由warning改为Ignore。然后Eclipse会重新编译程序,那些警告信息也就消失了。

struts架构下的网站经常出现javax.servlet.ServletException: BeanUtils.populate 错误,但是本地运行又一切正常,唯一觉得可能产生问题的就是服务器上跑了好几个网站,都是一样的架构的,怀疑是不是web容器把几个项目之间的java类给共用了,考虑到很多类都定义了serialVersionUID字段,然后尝试删除了某个类的serialVersionUID,结果关于该类的操作就恢复正常了。网上简单查阅了一下资料,感觉是tomcat把所有类串行化时候,由于我们的几个项目很多java类都是复制粘贴的,所以导致了很多类的serialVersionUID都是同一个值,所以tomcat会把不同项目的相同类名的类当作同一个类去处理,导致了这个奇怪的错误。

解决方案:
每个项目同名的类serialVersionUID改为不一样,不能直接的复制粘贴过来。
分享到:
评论

相关推荐

    java串行化详细的介绍了java串行化的概念

    #### 四、`serialVersionUID`的作用 在序列化的过程中,有一个重要的字段叫做`serialVersionUID`,它是一个长整型的值,用于标识类的不同版本。它的主要作用包括: - **兼容性验证**:当序列化的对象版本发生变化时...

    IDEA中实体类实现了序列化接口

    为了保证序列化的兼容性与一致性,Java引入了`serialVersionUID`字段来标识类的不同版本。当一个实现了`Serializable`接口的类没有显式地声明`serialVersionUID`时,JVM会根据类的信息自动生成一个。但在某些情况下...

    Java对象的序列化与反序列化Java开发Java经验技巧

    Java对象的序列化与反序列化是Java编程中一项重要的技术,它允许我们将Java对象转换为字节流,便于存储、传输或者在网络间传递。这一过程对于数据持久化、跨进程通信(如RMI,Remote Method Invocation)以及分布式...

    Java反序列化漏洞介绍书籍

    4. **自定义序列化与反序列化**:解释了如何使用`writeObject()`和`readObject()`方法以及`serialVersionUID`字段来自定义序列化行为,以确保安全性。 5. **Gadgets和Gadget Chains**:深入解释了gadgets的概念,...

    java序列化(Serializable)的作用和反序列化

    ### Java序列化(Serializable)的作用与反序列化详解 #### 一、序列化是什么? 序列化是指将程序中的对象转换为字节流的过程,从而方便存储或传输这些对象。通常,序列化用于将对象的状态(即其实例变量的值,而非...

    java技术指南

    关于序列化,文档探讨了如何实现Java对象的序列化和反序列化,以及为什么实现了Serializable接口的对象能够被序列化,包括默认序列化机制、SerialVersionUID的作用,以及序列化的影响因素和常见第三方库。...

    IO流与序列化

    8. **序列化版本ID**:讲解了serialVersionUID字段的重要性,用于确保反序列化时的兼容性。 9. **序列化策略**:介绍了如何控制哪些对象被序列化,以及处理循环引用问题。 通过学习IO流与序列化,开发者能够更好地...

    程序员面试题

    序列化与 serialVersionUID **序列化的意义:** 序列化是将对象的状态转换为字节流的过程,以便可以存储或在网络上传输。 **序列化 ID(serialVersionUID):** - **作用:** 用于标识类的不同版本,确保版本兼容...

    java LRU算法介绍与用法示例

    Java LRU算法介绍与用法示例 LRU(Least Recently Used,近期最少使用)算法是一种常用的缓存淘汰算法,它的思想是将长时间没有被利用的数据进行删除。该算法可以应用于缓存系统,例如在用户使用联网的软件的时候,...

    分布式部分概念

    #### SerialVersionUID的作用 `serialVersionUID`是一个版本标识符,用于区分不同版本的序列化对象。如果一个序列化的对象被反序列化时,其`serialVersionUID`与反序列化对象的版本标识符不匹配,将会抛出`...

    基于SpringMVC的全局异常处理器介绍

    private static final long serialVersionUID = 1L; private String message; public String getMessage() { return message; } public void setMessage(String message) { this.message = message; } ...

    自定义RPC的Java实现

    在现代软件开发中,分布式系统变得越来越普遍,其中远程过程调用(RPC)技术因其简单高效的特点而在跨网络节点间进行服务通信方面发挥着重要作用。本文将详细介绍如何在Java环境中自定义实现一个RPC框架,包括其实现...

    java反射机制简介

    #### 二、Java反射机制的作用 1. **动态获取类信息**:可以动态获取类的所有属性、方法等信息。 2. **创建实例**:可以动态创建某个类的实例。 3. **调用方法**:可以动态调用一个类的方法,包括私有方法。 4. **...

    java定时器.pdf

    本文将详细介绍Java定时器的使用方法以及在Web环境中的应用。 首先,让我们了解`Timer`类。`Timer`是定时器的实例,它负责调度任务的执行。创建一个`Timer`对象,然后调用其`schedule`系列方法来安排任务执行。例如...

    阿里巴巴Java开发手册(嵩山版).pdf

    - **原理介绍**:未明确指定初始容量时,HashMap将采用默认的容量值。当实际元素数量超过当前容量时,需要重新调整容量并进行重新哈希,这将导致性能下降。 - **优化建议**:基于预期的键值对数量来设置HashMap的...

    @SuppressWarnings

    #### 二、作用与用法 `@SuppressWarnings`注解的主要作用是告诉编译器忽略被注解的代码元素内部的某些警告。这种机制对于处理那些已知但不影响代码功能性的警告特别有用。 ##### 1. 使用场景 - **抑制特定类型的...

    jQuery-Easyui 多级菜单 前后台

    下面我们将详细介绍这段代码所涉及的关键知识点。 ### 一、jQuery-EasyUI简介 `jQuery-EasyUI`是一个基于jQuery的UI插件集合,它简化了网页前端开发中的UI设计工作。通过提供一系列易于使用的用户界面(UI)工具,...

    jsp页面中获取servlet请求中的参数的办法详解.docx

    private static final long serialVersionUID = 1L; public BBSServlet() { super(); } protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, ...

    jsp servlet javaBean后台分页实例代码解析.docx

    #### JavaBean与Service层的作用 - **JavaBean**:例如`ProjectBean`类,用来封装数据实体,如项目名称、描述等属性。 - **Service层**:如`SplitPage`类,实现了具体的业务逻辑,比如如何从数据库中获取数据并进行...

    java 自定义注解 经典学习文档

    - `serial`:当在可序列化的类上缺少`serialVersionUID`定义时的警告。 - `finally`:任何`finally`子句不能正常完成时的警告。 - `all`:关于以上所有情况的警告。 - **示例**: ```java @SuppressWarnings(...

Global site tag (gtag.js) - Google Analytics