【问题标题】:What exactly would happen is more than one class have same serial UIDs? [duplicate]如果多个类具有相同的序列 UID,究竟会发生什么? [复制]
【发布时间】:2014-08-12 19:04:44
【问题描述】:

我知道为什么我们需要提供一个串行 UID(以便在反序列化期间,发送方和接收方具有相同的加载类)。因此,根据这个,如果我有多个具有相似 UID 的类,那么我是否正确假设会发生反序列化但之后会出现问题(我不知道是什么)?还是它会以某种方式抛出InvalidClassException?还是我的两个假设都完全偏离了?

我想对此进行测试,但再次不确定它是否会起作用,如果在反序列化过程中实际选择了正确的类怎么办?在那种情况下,一切都会变得美好。

【问题讨论】:

  • 类总是由类名选择
  • 一切都会好起来的。该字段的主要目的是使反序列化能够处理单个序列化类的多个版本。如果您未指定 serialVersionUID,则会在编译时生成一个。如果您随后部署到集群 Java 应用程序服务器,并且它们序列化您的对象的状态,然后您要部署另一个构建,您将获得不同的生成 serialVersionUID,如果您尝试使用基本的应用程序服务器会给您一个错误反序列化。

标签: java


【解决方案1】:

不,一点也不。当通过反序列化重新创建实例时,其类由反序列化器加载。然后将此类序列 UID 与反序列化实例的 UID 进行比较,后者是序列化时类的 UID。只有当这两个 UID 不匹配时,才会抛出 InvalidClassException

例如,如果您将一个实例序列化为一个文件,停止您的 JVM,使用该实例的类的更改 UID 重新编译您的程序,重新启动应用程序并从前一个文件反序列化这个完全相同的实例,就会发生这种情况。 UID 旨在向应用程序发出信号,表明对类应用了不兼容的更改。

如果两个具有不同完全限定名称的类具有相同的 UID,这根本不会影响您的(反)序列化。供您参考,the Java documentation 是这样描述此事的:

序列化运行时为每个可序列化类关联一个版本号,称为serialVersionUID,在反序列化期间使用该版本号来验证序列化对象的发送方和接收方是否已为该对象加载了与序列化兼容的类.

如果接收者为对象加载了一个类,该对象的serialVersionUID 与相应发送者的类不同,则反序列化将导致InvalidClassException

可序列化类可以通过声明一个名为 serialVersionUID 的字段来显式声明自己的 serialVersionUID,该字段必须是 staticfinallong 类型。

正如您在另一条评论中所问的,为什么 serialVersionUID 字段的类型为 long,因为它可能更小。这可能是为了避免在您没有显式设置 serialVersionUID 但如果序列化程序隐式推断出冲突时发生冲突。在这种情况下,JVM 对一个 ID 进行散列处理,该 ID 很容易与较小范围的其他散列值发生冲突,例如 byte。如果您只为每次手动更改手动增加此数字,那么您当然不太可能耗尽long 的范围。一般来说,考虑到现在的内存价格,单个long 值并不太贵。

【讨论】:

  • 感谢您的解释,有道理
【解决方案2】:

不,不会发生任何不好的事情。序列化流包含序列化对象的类名。一旦读取了序列化对象的类名,Java 反序列化机制就会检查序列化的 UID 是否与本地类的 UID 相同。

【讨论】:

  • 那么有一个19位长的序列UID有什么特殊用途吗?这也可以很容易地成为一个小整数?
  • @noMAD 检查我的答案以获得关于此的理论。
猜你喜欢
  • 1970-01-01
  • 2022-11-27
  • 2017-06-10
  • 2015-12-25
  • 1970-01-01
  • 2014-11-01
  • 2017-01-01
  • 1970-01-01
  • 2015-10-23
相关资源
最近更新 更多