Newsletter sign-up
View all newsletters

Sign up for our technology specific newsletters.

Enterprise Java
Email Address:

Ensure proper version control for serialized objects

Java serialization and version control for release compatibility

  • Digg
  • Reddit
  • SlashDot
  • Stumble
  • del.icio.us
  • Technorati
  • dzone

Page 3 of 6

  • Add fields
  • Change a field from static to non-static
  • Change a field from transient to non-transient
  • Add classes to the object tree

Incompatible changes typically result from the removal of fields or objects from the object tree. As the default read-mechanism traverses the byte stream, it raises an exception when the target field no longer exists to accept the data. For example, when a class found in the prior version no longer exists in the evolved version, the default read-mechanism raises a ClassNotFound exception, whereas on a missing field, the InvalidArgumentException is raised.

Examples of incompatible changes include:

  • Delete fields
  • Change class hierarchy
  • Change non-static to static
  • Change non-transient to transient
  • Change type of a primitive field

For details on the compatible and incompatible Java type changes to a serializable class, see the Java Object Serialization Specification.

Having introduced the notion of a suid and the compatibility issues involving Java type changes, I am ready to discuss the importance of version control when using Java serialization. First, I present how Java serialization supports version control.

Release compatibility

To preserve an application's stability, release compatibility requires that a new version of an application run interchangeably with that of a prior version, with both exhibiting the same expected behavior. When release compatibility breaks, the client application can no longer run without having to be recompiled or even re-implemented.

With respect to Java serialization, release compatibility requires the following:

  1. A new version of a serializable class observes its externalized interface so that its client does not need to change.
  2. The evolved class can deserialize objects serialized by a prior version. Conversely, the prior class can deserialize objects serialized by the evolved class.

This level of compatibility is critical in supporting interoperability across releases in a mixed-version environment or in store-and-retrieve usage scenarios previously described.

In the store-and-retrieve scenario, an application serializes an object and stores it in the database. After this class is enhanced and released in a new application version, the application should be able to retrieve and deserialize the stored object into a runtime object.

In the mixed-release scenario, the producer-consumer relationship is bidirectional. The newly evolved serializable class must be able to deserialize the data serialized by one of a prior implementation. Conversely, the previously released serializable class must be able to deserialize the object serialized by a newer release.

Breaking serialization compatibility has serious consequences; some of which include:

  • Broken product migration: Software products may store the installation, configuration, and runtime state information as serialized objects. When serialization compatibility breaks, the new product version will not be able to read the data stored by the prior version, complicating the configuration of a new product release.
  • Broken mixed-version interoperability: When one or more products or applications share a serializable class, breaking serialization compatibility in such a class will result in these products or applications failing to exchange runtime objects between Java runtime instances.
  • Broken customer applications: Often, a customer application stores business transactions as serialized objects in a database. Subsequently, sometimes weeks or months later, the same application or another application retrieves these serialized objects from the database. If the serializable class used in an application is upgraded, resulting in incompatible serialization changes, the application will fail to deserialize these objects and generate a Java exception.


Java serialization and version control

The Java serialization mechanism provides an approach for version control. At the heart of Java serialization is the ObjectOutputStream class. It implements the computeSerialVersionUID() method to compute the suid during object serialization. This computed suid is then written to the serialized stream as a part of the serialized object. This suid in the stream serves as a marker to denote the version of the serializable class with which it is compatible. See Figure 2 for a sample of metadata stored in a serialized object.

  • Digg
  • Reddit
  • SlashDot
  • Stumble
  • del.icio.us
  • Technorati
  • dzone
Comment
Login
Forgot your account info?
Add comment
Anonymous comments subject to approval. Register here for member benefits.
Have a JavaWorld account? Log in here. Register now for a free account.
Resources