3

Background

I have a class, which has no serialization features overriden, and no serialVersionUID, but which still is serialized, stored, later deserialized. This is a configuration object, and when changing configuration, data is actually read from configuration UI, then object is created normally "from scratch" and serialized for storage. Only when it is used, object gets created by deserialization.

Now two fields got added to this class, which should not have been serialized, but were... This of course lead to some deserialization problems (NullPointerException when the fields were left null after default deserialization, breaking class invariants), solved by opening configuration UI and saving configuration, thus saving correct serialized form of the object.

Question

Now, what happens in deserialisation of object from saved configuration data, if I modify the class in one of these ways, to do a quick fix:

  1. remove these fields, and saved data is new version, with these fields in it?
  2. change these fields to transient, and saved data is new version, with these fields in it?
  3. change these fields to transient, and saved data is old version, without these fields?

To make this more concrete, let's say the added field is:

private final Map<String, String> extraProperties = new HashMap<String, String>(); 

And this is either removed from this class, or changed to private final transient field.

PS. No need to tell me, that custom serialization code should probably be added, and then the whole thing should probably be refactored, to separate persistent and transient data to different classes...

5
  • 1
    you could add a serialVersionUID to your new class that matches the (implicit) version it had before. this was done in some JDK classes like Vector to maintain backwards compatibility with older versions. then you could implement custom deserialization logic Commented Jan 11, 2013 at 8:29
  • You need to find out the serialVersionUID used in your existing data, and add that to your class if you want to continue to use the default serialization code. Commented Jan 11, 2013 at 8:30
  • Yeah, I know what to do to fix it properly. IOW, I know which chapter from Effective Java I need to re-read ;). But I did not readily find conclusive answers to my specific questions. Commented Jan 11, 2013 at 8:33
  • Ok, found a very related question: stackoverflow.com/questions/3960546/… Commented Jan 11, 2013 at 8:45
  • Java Serialization is particularly poor at handling changes to data structure. If you need support for this I suggest one of the text based serialization e.g. XStream or JSon or something of your own. Commented Jan 11, 2013 at 8:49

1 Answer 1

2

Remove (or make transient) these redundant fields you do not want to serialize. Then try to deserialize loading the old version where the non transient field, now removed, have been present. This will result an error of course, as the class serialVersionUID is now different. However both old and new serialVersionUID should be included in the message.

Now just define private static long serialVersionUID = in your class, setting it to old, previous value. The class content with excess fields in the file will be loaded, and the values of these excess fields will be ignored.

However you now have another problem: you probably have saved files of the two different types: old an new version. These will have different serialVersionUID so we can load one or another but not both. serialVersionUID is final, but maybe you can still set and probe different values as described here.

From the view point of serialization, changing field to transient is the same as field removal. It will not be stored and will not be loaded. However declaring the previously non transient field as transient will change the serialVersionUID if it is not fixed.

If item by item, if the serialVersionUID is now hardcoded and matches the serialVersionUID in the file, the answer to your question is:

  1. Nothing.
  2. Nothing.
  3. Nothing.

As "nothing" I mean that the class is deserialized without assigning values to the transient fields (if these are present) and no error is reported.

In case serialVersionUID's do not match, an exception is thrown, even if the rest of class matches.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.