java 正确使用序列化(5)
时间:2025-04-04
时间:2025-04-04
化技术 技术研究系列
2.2.2 序列化类多重版本的控制
如果在反序列化的JVM 里出现了该类的不同时期的版本,那么反序列化机制是如何处
理的呢?
为了避免这种问题,Java的序列化机制提供了一种指纹技术,不同的类带有不同版本的
指纹信息,通过其指纹就可以辨别出当前JVM 里的类是不是和将要反序列化后的对象对应
的类是相同的版本。该指纹实现为一个64bit的long 类型。通过安全的Hash算法(SHA-1)
来将序列化的类的基本信息(包括类名称、类的编辑者、类的父接口及各种属性等信息)处
理为该64bit的指纹。我们可以通过JDK自带的命令serialver来打印某个可序列化类的指纹
信息。如下:
当我们的两边的类版本不一致的时候,反序列化就会报错:
如何正确的使用Java序列化技术 技术研究系列
解决之道:从上面的输出可以看出,该指纹是通过如下的内部变量来提供的:
private static final long serialVersionUID;
如果我们在类里提供对该属性的控制,就可以实现对类的序列化指纹的自定义控制。为
此,我们在Person 类里定义该变量:
private static final long serialVersionUID= 6921661392987334380L;
则当我们修改了Person 类,发布不同的版本到反序列化端的JVM,也不会有版本冲突
的问题了。需要注意的是,serialVersionUID 的值是需要通过serialver 命令来取得。而不能
自己随便设置,否则可能有重合的。
需要注意的是,手动设置serialVersionUID 有时候会带来一些问题,比如我们可能对类
做了关键性的更改。引起两边类的版本产生实质性的不兼容。为了避免这种失败,我们需要
知道什么样的更改会引起实质性的不兼容,下面的表格列出了会引起实质性不兼容和可以忽
略(兼容)的更改:
更改类型 例子
兼容的更改
u 添加属性(Adding fields)
u 添加/删除类(adding/removing classes)
u 添加/删除writeObject/readObject方法(adding/removing
writeObject/readObject)
u 添加序列化标志(adding Serializable)
u 改变访问修改者(changing access modifier)
u 删除静态/不可序列化属性(removing static/transient from
a field)
不兼容的更改
u 删除属性(Deleting fields)
u 在一个继承或者实现层次里删除类(removing classes in a
hierarchy)
u 添加静态/不可序列化字段(adding static/transient to a
field)
u 修改简单变量类型(changing type of a primitive)
u switching between Serializable or Externalizable
u 删除序列化标志(removing Serializable/Externalizable)
u 改变readObject/writeObject对默认属性值的控制(changing
whether read
Object/writeObject handles default field
data)
u adding writeReplace or readResolve that produces
objects incompatible with older versions
另
下一篇:营龙煤业基本情况