如何处理包更改的Java序列化对象? [英] How to deal with a Java serialized object whose package changed?

查看:127
本文介绍了如何处理包更改的Java序列化对象?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个存储在HttpSession对象中的Java类,该对象在集群环境中的服务器之间进行序列化和传输。出于此解释的目的,我们将此类称为Person。

I have a Java class that is stored in an HttpSession object that's serialized and transfered between servers in a cluster environment. For the purpose of this explanation, lets call this class "Person".

在改进代码的过程中,此类已从com.acme.Person中移除tocom.acme.entity.Person。在内部,类保持完全相同(相同的字段,相同的方法,相同的一切)。

While in the process of improving the code, this class was moved from "com.acme.Person" to "com.acme.entity.Person". Internally, the class remains exactly the same (same fields, same methods, same everything).

问题是我们有两组服务器运行旧代码和新代码同时出现。
具有旧代码的服务器具有序列化的HttpSession对象,当新代码反序列化它时,它会抛出ClassNotFoundException,因为它找不到对com.acme.Person的旧引用。此时,处理这个很容易,因为我们可以使用新包重新创建对象。然后问题变成新服务器中的HttpSession将使用对com.acme.entity.Person的新引用来序列化对象,并且当在运行旧代码的服务器中对其进行反序列化时,将抛出另一个异常。在这一点上,我们不能再处理这个例外了。

The problem is that we have two sets of servers running the old code and the new code at the same time. The servers with the old code have serialized HttpSession object and when the new code unserializes it, it throws a ClassNotFoundException because it can't find the old reference to com.acme.Person. At this point, it's easy to deal with this because we can just recreate the object using the new package. The problem then becomes that the HttpSession in the new servers, will serialize the object with the new reference to com.acme.entity.Person, and when this is unserialized in the servers running the old code, another exception will be thrown. At this point, we can't deal with this exception anymore.

对于这种情况,最好的策略是什么?
有没有办法告诉新服务器通过引用旧包序列化对象并将旧包的引用反序列化为新包?
一旦所有服务器运行新代码,我们将如何过渡到使用新包并忘记旧包?

What's the best strategy to follow for this kind of cases? Is there a way to tell the new servers to serialize the object with the reference to the old package and unserialize references to the old package to the new one? How would we transition to using the new package and forgetting about the old one once all servers run the new code?

推荐答案

我发现这是博客文章声称有一个解决方案,但它没有非常清楚地说明。

I found this blog post that claims to have a solution, though it doesn't spell it out very clearly.

它实际上说的是你创建一个 ObjectInputStream 的子类,它会覆盖 readClassDescriptor 方法来做类似这样的事情:

What it is actually saying is that you create a subclass of ObjectInputStream that overrides the readClassDescriptor method to do something like this:

@Override
protected java.io.ObjectStreamClass readClassDescriptor() 
        throws IOException, ClassNotFoundException {
    ObjectStreamClass desc = super.readClassDescriptor();
    if (desc.getName().equals("oldpkg.Widget")) {
        return ObjectStreamClass.lookup(newpkg.Widget.class);
    }
    return desc;
};






你还应该看看这个问题及其答案,其中包含与您的问题相同的一些内容。


You should also look at this SO question and its answers which cover some of the same ground as your question.

我的建议是:不支持支持旧版本软件读取新版本序列化数据的情况。

My advice would be: don't support the case where old versions of software read data serialized by the new version.


  • 这是鼓励(实际上强迫)人们升级到最新版本代码库的好机会。一般来说,每个人的兴趣都是这种情况发生得越来越早。

  • This is a good opportunity to encourage (actually force) people to upgrade to the latest version of the code-base. Generally speaking, it is in everyone's interest that this happen sooner rather than later.

如果迫使人们升级为时过早出于其他原因,那么(IMO)您应该认真考虑退出您对类/包名称的更改。等到你有一个明确的升级策略/计划,1)技术上合理,2)所有利益相关者都可以接受。

If it is premature to force people to upgrade for other reasons, then (IMO) you should seriously consider backing out your changes to the class / package names. Wait until you've got a clear strategy / plan for upgrading that is 1) technically sound, and 2) acceptable to all stakeholders.

这篇关于如何处理包更改的Java序列化对象?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆