ObjectStreamClass: Peeking at a Java Object’s Serialization

ObjectStreamClass can be a useful class to analyze the serialization characteristics of a serialized class loaded in the JVM. This post looks at some of the information this class provides about a loaded serialized class.

ObjectStreamClass provides two static methods for lookup of a class: lookup(class) and lookupAny(Class). The first, lookup(Class), will only return an instance of ObjectStreamClass when the provided class is serializable and returns null if the provided class is not serializable. The second, lookupAny(Class) returns an instance of ObjectStreamClass for the provided class regardless of whether it’s serializable or not.

Once an instance of ObjectStreamClass is provided via the static “lookup” methods, that instance can be queried for class name, for serial version UID, and for serializable fields.

To demonstrate use of ObjectStreamClass, I first list the code listings for two simple classes that will be part of the demonstration. One class, Person, is Serializable, but has a transient field. The other class, UnserializablePerson, is nearly identical, but it is not Serializable.

Person.java

package dustin.examples.serialization;

import java.io.Serializable;

/**
 * Person class intended for demonstration of ObjectStreamClass.
 * 
 * @author Dustin
 */
public class Person implements Serializable
{
   private final String lastName;
   private final String firstName;
   transient private final String fullName;

   public Person(final String newLastName, final String newFirstName)
   {
      this.lastName = newLastName;
      this.firstName = newFirstName;
      this.fullName = this.firstName + " " + this.lastName;
   }

   public String getFirstName()
   {
      return this.firstName;
   }

   public String getLastName()
   {
      return this.lastName;
   }

   public String getFullName()
   {
      return this.fullName;
   }

   @Override
   public String toString()
   {
      return this.fullName;
   }
}

UnserializablePerson.java

package dustin.examples.serialization;

/**
 * Person class intended for demonstration of ObjectStreamClass.
 * 
 * @author Dustin
 */
public class UnserializablePerson
{
   private final String lastName;
   private final String firstName;
   private final String fullName;

   public UnserializablePerson(final String newLastName, final String newFirstName)
   {
      this.lastName = newLastName;
      this.firstName = newFirstName;
      this.fullName = this.firstName + " " + this.lastName;
   }

   public String getFirstName()
   {
      return this.firstName;
   }

   public String getLastName()
   {
      return this.lastName;
   }

   public String getFullName()
   {
      return this.fullName;
   }

   @Override
   public String toString()
   {
      return this.fullName;
   }
}

With two classes in place to run use in conjunction with ObjectStreamClass, it’s now time to look at a simple demonstration application that shows use of ObjectStreamClass.

ObjectStreamClassDemo.java

package dustin.examples.serialization;

import static java.lang.System.out;

import java.io.ObjectStreamClass;
import java.io.ObjectStreamField;

/**
 * Demonstrates use of ObjectStreamDemo.
 * 
 * @author Dustin
 */
public class ObjectStreamClassDemo
{
   /**
    * Displays class name, serial version UID, and serializable fields as
    * indicated by the provided instance of ObjectStreamClass.
    * 
    * @param serializedClass 
    */
   public static void displaySerializedClassInformation(
      final ObjectStreamClass serializedClass)
   {
      final String serializedClassName = serializedClass.getName();
      out.println("Class Name: " + serializedClassName);
      final long serializedVersionUid = serializedClass.getSerialVersionUID();
      out.println("serialversionuid: " + serializedVersionUid);
      final ObjectStreamField[] fields = serializedClass.getFields();
      out.println("Serialized Fields:");
      for (final ObjectStreamField field : fields)
      {
         out.println("\t" + field.getTypeString() + " " + field.getName());
      }
   }

   /**
    * Main function that demonstrates use of ObjectStreamDemo.
    * 
    * @param arguments Command line arguments; none expected.
    */
   public static void main(String[] arguments)
   {
      // Example 1: ObjectStreamClass.lookup(Class) on a Serializable class
      out.println("\n=== ObjectStreamClass.lookup(Serializable) ===");
      final ObjectStreamClass serializedClass = ObjectStreamClass.lookup(Person.class);
      displaySerializedClassInformation(serializedClass);

      // Example 2: ObjectStreamClass.lookup(Class) on a class that is not
      //            Serializable (which will result in a NullPointerException
      //            when trying to access null returned from 'lookup'
      out.println("\n=== ObjectStreamClass.lookup(Unserializable) ===");
      try
      {
         final ObjectStreamClass unserializedClass =
            ObjectStreamClass.lookup(UnserializablePerson.class);
         displaySerializedClassInformation(unserializedClass);
      }
      catch (NullPointerException npe)
      {
         out.println("NullPointerException: Unable to lookup unserializable class with ObjectStreamClass.lookup.");
      }

      // Example 3: ObjectStreamClass.lookupAny(Class) works without the
      //            NullPointerException, but only provides name of the class as
      //            Serial Version UID and serialized fields do not apply in the
      //            case of a class that is not serializable.
      out.println("\n=== ObjectStreamClass.lookupAny(Unserializable) ===");
      final ObjectStreamClass unserializedClass =
          ObjectStreamClass.lookupAny(UnserializablePerson.class);
      displaySerializedClassInformation(unserializedClass);
   }
}

The comments in the source code above indicate what is being demonstrated. The output from running this class is shown in the next screen snapshot.

outputObjectStreamClassDemo

When the output shown above is correlated with the code before it, we can make several observations related to ObjectStreamClass. These include the fact that the transient field of a serializable class is not returned as one of the serializable fields. We also see that ObjectStreamClass.lookup(Class) method returns null if the class provided to it is not serializable. ObjectStreamClass.lookupAny(Class) returns an instance of ObjectStreamClass for classes that are not serializable, but only the class’s name is available in that case.

The code above showed a Serial Version UID for Person.java of 1940442894442614965. When serialver is run on the command line, the same Serial Version UID is generated and displayed.

serialverOnPersonPowerShell

What’s nice about the ability to programatically calculate the same Serial Version UID as would be calculated by the serialver tool that comes with the Oracle JDK is that one could explicitly add the same Serial Version UID to generated code as would be implicitly added anyway. Any JVM-friendly script or tool (such as one written in Groovy) that needs to know the implicit Serial Version UID of a class could use ObjectStreamClass to obtain that Serial Version UID.
 

Do you want to know how to develop your skillset to become a Java Rockstar?

Subscribe to our newsletter to start Rocking right now!

To get you started we give you two of our best selling eBooks for FREE!

JPA Mini Book

Learn how to leverage the power of JPA in order to create robust and flexible Java applications. With this Mini Book, you will get introduced to JPA and smoothly transition to more advanced concepts.

JVM Troubleshooting Guide

The Java virtual machine is really the foundation of any Java EE platform. Learn how to master it with this advanced guide!

Given email address is already subscribed, thank you!
Oops. Something went wrong. Please try again later.
Please provide a valid email address.
Thank you, your sign-up request was successful! Please check your e-mail inbox.
Please complete the CAPTCHA.
Please fill in the required fields.

Leave a Reply


four × = 12



Java Code Geeks and all content copyright © 2010-2014, Exelixis Media Ltd | Terms of Use | Privacy Policy | Contact
All trademarks and registered trademarks appearing on Java Code Geeks are the property of their respective owners.
Java is a trademark or registered trademark of Oracle Corporation in the United States and other countries.
Java Code Geeks is not connected to Oracle Corporation and is not sponsored by Oracle Corporation.
Do you want to know how to develop your skillset and become a ...
Java Rockstar?

Subscribe to our newsletter to start Rocking right now!

To get you started we give you two of our best selling eBooks for FREE!

Get ready to Rock!
You can download the complementary eBooks using the links below:
Close