Redis Serialization and Deserialization

Vic Cebedo picture Vic Cebedo · Jun 12, 2015 · Viewed 12.3k times · Source

I have noticed that some of my serialized objects stored in Redis have problems deserializing.

This typically occurs when I make changes to the object class being stored in Redis.

I want to understand the problem so that I can have a clear design for a solution.

My question is, what causes deserialization problems? Would a removal of a public/private property cause a problem? Adding new properties, perhaps? Would a adding a new function to the class create problems? How about more constructors?

In my serialized object, I have a property Map, what if I change (updated some properties, added functions, etc) myObject, would it cause a deserialization problem?

Answer

Sathish picture Sathish · Jun 12, 2015

what causes deserialization problems?

I would like to give you bit of background before answering your question,

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.

If a serializable class does not explicitly declare a serialVersionUID, then the serialization runtime will calculate a default serialVersionUID value for that class based on various aspects of the class, It uses the following information of the class to compute SerialVersionUID,

  1. The class name.
  2. The class modifiers written as a 32-bit integer.
  3. The name of each interface sorted by name.
  4. For each field of the class sorted by field name (except private static and private transient fields:
  5. The name of the field.
  6. The modifiers of the field written as a 32-bit integer.
  7. The descriptor of the field.
  8. if a class initializer exists, write out the following:

    The name of the method, .

    The modifier of the method, java.lang.reflect.Modifier.STATIC, written as a 32-bit integer.

    The descriptor of the method, ()V.

  9. For each non-private constructor sorted by method name and signature:

    The name of the method, .

    The modifiers of the method written as a 32-bit integer.

    The descriptor of the method.

  10. For each non-private method sorted by method name and signature:

    The name of the method.

    The modifiers of the method written as a 32-bit integer.

    The descriptor of the method.

So, to answer your question,

Would a removal of a public/private property cause a problem? Adding new properties, perhaps? Would a adding a new function to the class create problems? How about more constructors?

Yes, all these additions/removal by default will cause the problem.

But one way to overcome this is to explicitly define the SerialVersionUID, this will tell the serialization system that i know the class will evolve (or evolved) over the time and don't throw an error. So the de-serialization system reads only those fields that are present in both the side and assigns the value. Newly added fields on the de-serialization side will get the default values. If some fields are deleted on the de-serialization side, the algorithm just reads and skips.

Following is the way one can declare the SerialVersionUID,

private static final long serialVersionUID = 3487495895819393L;