我正在研究 Java 序列化机制中的不同选项,以允许我们的类结构具有灵活性以进行版本容错存储(并且提倡使用不同的机制,您无需告诉我)。
例如,如果只需要向后兼容,默认的序列化机制可以处理添加和删除字段。
然而,重命名一个类或将其移动到不同的包已被证明要困难得多。我在这个问题中发现,通过继承 ObjectInputStream 并覆盖 readClassDescriptor(),我能够进行简单的类重命名和/或移动包:
if (resultClassDescriptor.getName().equals("package.OldClass"))
resultClassDescriptor = ObjectStreamClass.lookup(newpackage.NewClass.class);
这对于简单的重命名很好。但是,如果您随后尝试添加或删除字段,则会收到 java.io.StreamCorruptedException。更糟糕的是,即使添加或删除了一个字段,然后重命名该类,也会发生这种情况,这可能会导致多个开发人员或多个签入出现问题。
根据我所做的一些阅读,我尝试了一些覆盖resolveClass()的方法,我们的想法是我们正确地将名称重新指向新类,而不是加载旧类本身并轰炸字段更改。但这来自对序列化机制的一些细节的非常模糊的理解,我什至不确定我是否在吠叫正确的树。
所以2个精确的问题:
- 为什么使用 readClassDescriptor() 重新指向类名会导致反序列化在正常、兼容的类更改时失败?
- 有没有办法使用 resolveClass() 或其他机制来解决这个问题并允许类同时进化(添加和删除字段)并重命名/重新打包?
我四处寻找,找不到关于 SO 的等效问题。无论如何,如果存在这样的问题,请向我指出,但请仔细阅读该问题,以免关闭我,除非另一个问题实际上回答了我的确切问题。