Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

SerialVersionUID in the Java standard library across different JVMs

Based on the description of SerialVersionUID here: https://docs.oracle.com/javase/8/docs/platform/serialization/spec/class.html#a4100, it seems necessary to always include SerialVersionUID in any classes you create so that a JVM used for serialization and a different JVM used for deserialzation won't automatically assign their own SerialVersionUIDs, which have potential to be different from one another because of differences in the JVM. This works well for controlling deserialzation of my own classes, but what if I want to ensure that classes in the standard library serialized with JVM A can be deserialized by JVM B?

Map<Integer, String> myMap = new HashMap<>();

HashMap defines a SerialVersionUID. But:

  • Since HashMap lives in the java standard library, am I provided any sort of guarantee that if I serialize this HashMap with JVM A that JVM B will be able to deserialize it? Namely, is JVM B allowed to specify a different SerialVersionUID than JVM A, at least if B is just a minor version upgrade from A?
  • If it's not guaranteed for standard library classes, does using SerialVersionUID only really ensure proper deserialization for your own classes that never touch the java standard library? For example, a class that looks like this:

    public class NewClass implements Serializable
    {
        private static final long serialVersionUID = 1L;
    
        private final Map<Integer, String> myMap;
    
        public NewClass()
        {
            this.myMap = new HashMap<>();
        }
    }
    

    would be prone to failure because deserialization depends on HashMap having the same SerialVersionUID, which could be different in different JVMs, right?

like image 377
Nile Avatar asked Mar 01 '18 19:03

Nile


People also ask

What is serialVersionUID used for in Java?

SerialVersionUID is a unique identifier for each class, JVM uses it to compare the versions of the class ensuring that the same class was used during Serialization is loaded during Deserialization. Specifying one gives more control, though JVM does generate one if you don't specify.

Can two classes have same serialVersionUID?

Technically you can't prevent two classes from having the same serial version UID, much like you can't prevent two objects from having the same system hash code.

What is serialVersionUID in Java exception?

The serialization at runtime associates with each serializable class a version number called a serialVersionUID, which is used during deserialization to verify that the sender and receiver of a serialized object have loaded classes for that object that are compatible with respect to serialization.

Is serialVersionUID mandatory in Java?

Bullet Points. Defining a serialVersionUID field in a serializable class is not mandatory.


1 Answers

Potentially yes, you are correct.

Actually this has happened to us a while ago with some swing classes (I really can't remember which exactly), but serializing on jdkX and de-serailizng them on jdkX+1 (that was a really long time ago, sorry for missing these details), things started to break with InvalidClassException. We had paid support at the time and opened an issue - the response was, well, that those class(es) changed in such a way that it would be impossible to deserialize them back properly - you are stuck with this version, or upgrade to jdk+1 and use that. It has not happened to me since then, not even once.

Generally, I think, this is what makes serialization hard too. You have to maintain such a process, so that changes in the future versions can be made relevant and compatible with previous ones, from a serialization point of view.

On the other note, HashMap has a very smart way to serialize it's data. It serializes (among other things likes load_factor, etc) only it's keys and values - nothing else. So no matter if the implementation changes, they will be possible to be de-serialzied. For this reason, some of the fields that would not be needed are marked as transient, for example:

 transient int modCount;
 transient Set<Map.Entry<K,V>> entrySet;

The idea is that it should serialize data vs structure.


If HashMap changes in such a way that Serialization would break in jdk-11 for example, this would make a lot of developers angry, I doubt this would ever be a path taken (unless really needed)

like image 170
Eugene Avatar answered Oct 13 '22 19:10

Eugene