0

Consider the following situation, described in question How can I deserialize the object, if it was moved to another package or renamed? by dma_k:

There is a serialization file, created by the older version of the application. Unfortunately, the package has changed for the class, that has been serialized. And now I need to load the information from this file into the same class, but located in different package. This class has serialVersionUID defined and has not changed (i.e. is compatible).

Question was: Is it possible to load the new class instances from this file using any tricks (except trivial copying the class into old package and then using the deserialization wrapper logic)? ...

Solution was "class HackedObjectInputStream extends ObjectInputStream" by Igor Nardin:

class HackedObjectInputStream extends ObjectInputStream {

    public HackedObjectInputStream(InputStream in) throws IOException {
        super(in);
    }

    @Override
    protected ObjectStreamClass readClassDescriptor() throws IOException, ClassNotFoundException {
        ObjectStreamClass resultClassDescriptor = super.readClassDescriptor();

        if (resultClassDescriptor.getName().equals("oldpackage.Clazz"))
            resultClassDescriptor = ObjectStreamClass.lookup(newpackage.Clazz.class);

        return resultClassDescriptor;
    }
}

Follow-up question Is it possible to write the new class instances to a file in a backward compatible way (explicitly setting the class name)? The goal is that older applications can read the files written by the new application (with the package name changed).

How would a "class HackedObjectOutputStream extends ObjectOutputStream" look like?

public class HackedObjectOutputStream extends ObjectOutputStream {

    public HackedObjectOutputStream(OutputStream out) throws IOException {
        super(out);
    }

    @Override
    public final void writeObjectOverride(Object obj) throws IOException {
    // How to change the package.class name ?
    }
}
Community
  • 1
  • 1
qwert2003
  • 801
  • 6
  • 9

1 Answers1

0

With the readResolve() and writeReplace() methods.

user207421
  • 305,947
  • 44
  • 307
  • 483
  • Where to put these methods? Some more hints? – qwert2003 Jan 02 '16 at 22:13
  • It's all described in the Object Serialization Specification. – user207421 Jan 03 '16 at 08:54
  • The [O.S.Specification](https://docs.oracle.com/javase/7/docs/platform/serialization/spec/output.html#5324) says: For Serializable classes, the writeReplace method allows a class of an object to nominate its own replacement in the stream before the object is written... Does this mean: - the writeReplace method must be put into the class that actually is saved (not into HackedObjectOutputStream)? - a copy of the class with the old package name must be maintained? - it is not possible to just rename the package when serializing? – qwert2003 Jan 03 '16 at 22:02