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

问题描述 投票:7回答:1

基于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<>();

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中可能会有所不同,对吧?
java serialization serialversionuid
1个回答
1
投票

可能是的,你是对的。

实际上这已经发生在我们不久前的一些swing课程(我真的不记得究竟是哪一个),但序列化jdkX并在jdkX+1 de-serailizng他们(那是很久以前的事,抱歉错过了这些细节)事情开始与InvalidClassException决裂。我们当时已经支付了支持并且开了一个问题 - 响应是,那些类别改变了以至于无法正确地反序列化它们 - 你被这个版本困住了,或者升级到jdk+1并使用它。从那以后,我没有发生过这种情况,甚至没有发生过一次。

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

另一方面,HashMap有一种非常聪明的方法来序列化它的数据。它序列化(除了其他东西,如load_factor等)只有它的键和值 - 没有别的。因此,无论实施是否发生变化,都可以进行反序列化。出于这个原因,一些不需要的字段被标记为瞬态,例如:

 transient int modCount;
 transient Set<Map.Entry<K,V>> entrySet;

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


例如,如果HashMap以序列化在jdk-11中破坏的方式发生变化,这会让很多开发人员生气,我怀疑这将是一条路径(除非确实需要)

© www.soinside.com 2019 - 2024. All rights reserved.