如何使用各种SerialVersionUID反序列化Java对象?

如何使用各种SerialVersionUID反序列化Java对象?,java,serialization,serialversionuid,Java,Serialization,Serialversionuid,假设我有一个类Foo,它在过去有serialVersionUIDs1、3和17,我需要能够将所有三个版本读入Foo实例。我该怎么做 我特别需要知道哪个版本保存在字节流中,以便进行一些数据迁移。如何访问readObject()中的serialVersionUID?还是已经太晚了?这不容易,但有可能。对于类的每个历史版本,您需要创建单独的类加载器,它将加载数据模型类的旧版本。然后,您需要尝试使用每个类加载器读取您的文件,直到找到合适的类加载器。我相信ObjectInputStream使用线程上下文中

假设我有一个类
Foo
,它在过去有
serialVersionUID
s1、3和17,我需要能够将所有三个版本读入
Foo
实例。我该怎么做


我特别需要知道哪个版本保存在字节流中,以便进行一些数据迁移。如何访问
readObject()
中的
serialVersionUID
?还是已经太晚了?

这不容易,但有可能。对于类的每个历史版本,您需要创建单独的类加载器,它将加载数据模型类的旧版本。然后,您需要尝试使用每个类加载器读取您的文件,直到找到合适的类加载器。我相信
ObjectInputStream
使用线程上下文中的当前类加载器。如果你需要更多的细节,可以随时问我

后面的补充:指定
ObjectInputStream
将使用哪个类加载器似乎不是那么容易。这里可能需要额外的调查


后面的另一个添加:可能您可以覆盖
ObjectInputStream
中的
resolveClass(ObjectStreamClass)
方法,以便使用适当的类加载器。

使用不同的类加载器来反序列化对象的不同版本。之后,您必须根据以前的版本手动初始化公共(可能是最新)实例的内部状态(您必须为此编写一个转换器)


确保类加载器路径完全不同如果超级类加载器可以加载一个类,它将加载。因此,所有类加载器应该彼此完全分离(两者都不应该是其他类的超级加载器)。

通过在反序列化过程中捕获错误,可以获得前一个
serialVersionUID

try {
  // deserialize here...
} catch (final java.io.InvalidClassException e) {
  System.out.println(e.getMessage());
  // The message string contains the former uid.
  // Message: local class incompatible: stream classdesc serialVersionUID = OLD_UID_HERE, local class serialVersionUID = NEW_UID_HERE
}

看看这个:好的,但是他将如何获得数据呢?他可以解析消息吗?至少uid没有丢失,他可以基于此执行一些迁移过程。当然他不会。但是他可以检查旧的源代码并进行迁移(你回答他的问题的第1点),我只回答关于如何查找旧uid的部分。谢谢:)如果数据结构没有任何更改,并且序列化将进入对象准备就绪的某个阶段,那么你的解决方案可能会起作用,但“只是”uid是不同的。但我认为如果宫内节育器不同,反序列化会立即停止。它会停止,但有提到的例外。但这是获取旧uid并做出决定的第一步(根据classloader使用…,不确定该部分),我可能必须重写
readClassDescriptor()
:-/请参见此答案