4

I know why we need to provide a serial UID (so that during de-serialization, the sender and receiver have the same loaded class). So according to this, if I have multiple classes with similar UID's then am I correct in assuming that deserialization would occur but something (I don't know what) would go wrong after? Or is it that it would somehow throw an InvalidClassException? Or am I totally way off in both my assumptions?

I wanted to test this out but again am not certain if it would work cause what if during deserialization the correct class actually gets picked? In that case everything would be peachy.

noMAD
  • 7,744
  • 19
  • 56
  • 94
  • Class always picked by a class name – kan Aug 12 '14 at 19:07
  • Everything would be fine. The primary purpose of that field is to enable de-serialization to work with multiple versions of a single serialized class. If you don't specify a serialVersionUID one is generated at compile time. If you then deployed to clustered Java application servers, and they serialize the state of your Object, and then you were to deploy another build you would get a different generated serialVersionUID and the app server would give you an error if you then tried to use basic deserialization. – Elliott Frisch Aug 12 '14 at 19:08

2 Answers2

8

No, not at all. When an instance is recreated by deserialization, its class is loaded by the deserializer. This classes serial UID is then compared to the deserialized instance's UID which is that of the class at the time of serialization. Only if these two UIDs do not match, an InvalidClassException is thrown.

This happens for example if you serialize an instance to a file, stop your JVM, recompile your program with a changed UID for this instance's class, restart the application and deserialize this very same instance from the former file. The UID is meant to signal to the application that a non-compatible change was applied to the class.

If two classes with different fully-qualified names have the same UID, this does not affect your (de-)serialization at all. For your reference, this is how the Java documentation describes the matter:

The serialization 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.

If the receiver has loaded a class for the object that has a different serialVersionUID than that of the corresponding sender's class, then deserialization will result in an InvalidClassException.

A serializable class can declare its own serialVersionUID explicitly by declaring a field named serialVersionUID that must be static, final, and of type long.

As you asked in another comment why the serialVersionUID field is of type long as it could be smaller. This is probably meant to avoid collisions when you do not explicitly set a serialVersionUID but if one is inferred implicitly by the serializer. In this case, the JVM hashes an ID which might collide easily with other hashed values for smaller ranges such as byte. If you only manually increment this number for each manual change, it is of course rather unlikely that you ever exhaust the range of long. In general, a single long value is neither too expensive when you consider memory prices these days.

Rafael Winterhalter
  • 42,759
  • 13
  • 108
  • 192
1

No, nothing bad would happen. The serialized stream contains the name of the class of the serialized objects. Once the name of the class of a serialized object is read, the Java deserialization mechanism checks that the serialized UID is identical to the one of the local class.

JB Nizet
  • 678,734
  • 91
  • 1,224
  • 1,255