一尘不染

Redis序列化和反序列化

redis

我注意到存储在Redis中的某些序列化对象在反序列化方面遇到问题。

当我对Redis中存储的对象类进行更改时,通常会发生这种情况。

我想了解问题,以便为解决方案设计一个清晰的方案。

我的问题是,什么导致反序列化问题?移除公共/私人财产会引起问题吗?也许添加新属性?向类添加新功能会产生问题吗?那么更多的构造函数呢?

在我的序列化对象中,我有一个属性Map,如果我更改(更新了一些属性,添加了功能等)myObject,会导致反序列化问题吗?


阅读 1617

收藏
2020-06-20

共1个答案

一尘不染

什么原因导致反序列化问题?

在回答您的问题之前,我想给您一些背景知识,

序列化运行时与每个可序列化的类关联一个版本号,称为serialVersionUID,在反序列化期间使用该版本号来验证序列化对象的发送者和接收者是否已加载了该对象的与序列化兼容的类。如果接收者已为该对象加载了一个与相应发送者类具有不同的serialVersionUID的类,则反序列化将导致InvalidClassException。

如果可序列化的类未明确声明serialVersionUID,则序列化运行时将根据该类的各个方面为该类计算默认的serialVersionUID值,它将使用该类的以下信息来计算SerialVersionUID,

  1. 类名。
  2. 类修饰符写为32位整数。
  3. 每个接口的名称按名称排序。
  4. 对于按字段名称排序的类的每个字段(私有静态字段和私有瞬态字段除外:
  5. 字段名称。
  6. 以32位整数形式编写的字段的修饰符。
  7. 字段的描述符。
  8. 如果存在类初始值设定项,则写出以下内容:

方法的名称。

方法的修饰符java.lang.reflect.Modifier.STATIC,用32位整数表示。

方法的描述符()V。

  1. 对于按方法名称和签名排序的每个非私有构造函数:

方法的名称。

方法的修饰符,写为32位整数。

方法的描述符。

  1. 对于按方法名称和签名排序的每个非私有方法:

方法的名称。

方法的修饰符,写为32位整数。

方法的描述符。

因此,为了回答您的问题,

移除公共/私人财产会引起问题吗? 也许添加新属性?向类添加新功能会产生问题吗?那么更多的构造函数呢?

是的,默认情况下,所有这些添加/删除操作都会导致此问题。

但是解决此问题的一种方法是显式定义SerialVersionUID,这将告诉序列化系统我知道该类将随着时间的推移而发展(或发展)并且不会引发错误。因此,反序列化系统仅读取双方都存在的那些字段并分配值。反序列化方面的新添加字段将获得默认值。如果在反序列化方面删除了某些字段,则该算法只会读取和跳过。

以下是声明SerialVersionUID的方法,

private static final long serialVersionUID = 3487495895819393L;
2020-06-20