跨越不同JVM的Java标准库中的SerialVersionUID

Nil*_*ile 8 java serialization serialversionuid

基于SerialVersionUID的描述:https://docs.oracle.com/javase/8/docs/platform/serialization/spec/class.html#a4100 ,似乎必须始终在您创建的任何类中包含SerialVersionUID,以便用于序列化的JVM和用于反序列化的不同JVM不会自动分配它们自己的SerialVersionUID,由于JVM的不同,它们可能彼此不同.这适用于控制我自己的类的反序列化,但是如果我想确保JVM B序列化的标准库中的类可以被JVM B反序列化呢?

Map<Integer, String> myMap = new HashMap<>();
Run Code Online (Sandbox Code Playgroud)

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<>();
        }
    }
    
    Run Code Online (Sandbox Code Playgroud)

    因为反序列化依赖于具有相同SerialVersionUID的HashMap,这在不同的JVM中可能会有所不同,对吧?

Eug*_*ene 2

可能是的,你是对的。

实际上,不久前,我们的一些swing类就发生过这种情况(我真的记不清到底是哪个),但是序列化jdkX和反序列化它们jdkX+1(那是很久以前的事了,很抱歉错过了这些细节),事情就开始了与 决裂InvalidClassException。我们当时支付了支持并提出了一个问题 - 响应是,好吧,这些类的更改方式使得无法正确反序列化它们 - 你被困在这个版本中,或者升级到jdk+1并使用它。从那以后,这种事就再没有发生在我身上,一次也没有。

一般来说,我认为这也是序列化变得困难的原因。您必须维护这样一个流程,以便从序列化的角度来看,未来版本中的更改可以与以前的版本相关并兼容。

另一方面,HashMap有一种非常智能的方法来序列化其数据。它仅序列化(以及其他事物load_factor,例如 等)它的键和值 - 没有其他。因此,无论实现是否发生变化,它们都可以被反序列化。因此,一些不需要的字段被标记为瞬态,例如:

 transient int modCount;
 transient Set<Map.Entry<K,V>> entrySet;
Run Code Online (Sandbox Code Playgroud)

这个想法是它应该序列化数据与结构。


例如,如果HashMap以序列化闯入的方式进行更改jdk-11,这会让很多开发人员感到愤怒,我怀疑这是否会成为一条路径(除非确实需要)