How to deal with a Java serialized object whose package changed?

一笑奈何 提交于 2019-11-30 06:36:44
Stephen C

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

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.

  • 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.

This is always a big headache with Java serialization. As long as you're migrating your classes anyway, I'd recommend looking into migrating toward a different serialization mechanism like XStream. There's an interesting article on this at JavaLobby.

In some cases you don't have access to the ObjectInputStream, and you can't override readClassDescriptor(). For example, another subsystem serializes and deserializes these objects. In our case, we had legacy instances serialized in Quartz job data maps.

For this case, you have to maintain a shallow definition of the old class. You can implement the old class's readResolve() and writeReplace() methods.

class OldClass{
  private int aField;
  private Object readResolve() throws ObjectStreamException {
     return new NewClass(aField);
  }
  private Object writeReplace() throws ObjectStreamException {
     return new NewClass(aField);
  }
}
mP.

You're screwed, bounce the old servers if you're happy to promote your changes. Any hack to achieve your goal will just add more crap code and makes for more mess and headaches.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!