跨不同 JVM 的 Java 标准库中的 SerialVersionUID
Posted
技术标签:
【中文标题】跨不同 JVM 的 Java 标准库中的 SerialVersionUID【英文标题】:SerialVersionUID in the Java standard library across different JVMs 【发布时间】:2018-08-09 22:49:20 【问题描述】:根据此处对 SerialVersionUID 的描述:https://docs.oracle.com/javase/8/docs/platform/serialization/spec/class.html#a4100,似乎有必要在您创建的任何类中始终包含 SerialVersionUID,以便用于序列化的 JVM 和用于反序列化的不同 JVM 不会自动分配它们自己的 SerialVersionUID,由于JVM的差异,它们有可能彼此不同。这对于控制我自己的类的反序列化效果很好,但是如果我想确保标准库中用 JVM A 序列化的类可以被 JVM B 反序列化怎么办?
Map<Integer, String> myMap = new HashMap<>();
HashMap 定义了一个 SerialVersionUID。但是:
既然 HashMap 存在于 java 标准库中,我是否提供了任何形式的保证,如果我用 JVM A 序列化这个 HashMap,JVM B 将能够反序列化它?也就是说,是否允许 JVM B 指定与 JVM A 不同的 SerialVersionUID,至少如果 B 只是从 A 升级的次要版本?如果标准库类不能保证,那么使用 SerialVersionUID 是否真的只能确保您自己的类从不接触 java 标准库的正确反序列化?例如,一个如下所示的类:
public class NewClass implements Serializable
private static final long serialVersionUID = 1L;
private final Map<Integer, String> myMap;
public NewClass()
this.myMap = new HashMap<>();
很容易失败,因为反序列化依赖于具有相同 SerialVersionUID 的 HashMap,这在不同的 JVM 中可能会有所不同,对吧?
【问题讨论】:
【参考方案1】:可能是的,你是对的。
实际上这发生在我们之前的一些 swing
类(我真的不记得到底是哪个),但在 jdkX
上序列化并在 jdkX+1
上对它们进行反序列化(那真的很长前段时间,很抱歉错过了这些细节),事情开始与InvalidClassException
发生冲突。我们当时已经支付了支持并打开了一个问题 - 响应是,这些类以这样的方式发生了变化,以至于无法正确反序列化它们 - 你被这个版本卡住了,或者升级到jdk+1
并使用它。从那以后没有发生在我身上,一次也没有。
一般来说,我认为这也是让序列化变得困难的原因。您必须维护这样一个过程,以便从序列化的角度来看,未来版本中的更改可以与以前的版本相关并兼容。
另一方面,HashMap
有一种非常聪明的方法来序列化它的数据。它序列化(除其他外,如load_factor
等)仅它是键和值 - 仅此而已。因此,无论实现是否发生变化,它们都可能被反序列化。出于这个原因,一些不需要的字段被标记为瞬态,例如:
transient int modCount;
transient Set<Map.Entry<K,V>> entrySet;
这个想法是它应该序列化数据与结构。
如果HashMap
以这样的方式发生变化,例如,序列化会在jdk-11
中中断,这会让很多开发人员生气,我怀疑这是否会成为一条路径(除非真的 需要)
【讨论】:
每个 Swing 类在 Javadoc 中都有一个警告,说明可能跨 JDK 版本的序列化不兼容。 @EJP 哦!现在这是有道理的......谢谢你以上是关于跨不同 JVM 的 Java 标准库中的 SerialVersionUID的主要内容,如果未能解决你的问题,请参考以下文章