Java ObjectStreamClass Class
Last modified: April 16, 2025
The java.io.ObjectStreamClass
class provides serialization metadata
about classes. It contains the name and serialVersionUID of serializable classes.
This class is used internally by Java's serialization mechanism.
ObjectStreamClass
describes classes that are serialized or
deserialized. It acts as a serialization descriptor, holding class name, fields,
and version information. The class is primarily used by ObjectInputStream and
ObjectOutputStream.
ObjectStreamClass Class Overview
ObjectStreamClass
provides information about serializable classes.
Key methods include getting class name, serialVersionUID, and field descriptors.
The class cannot be instantiated directly by applications.
public class ObjectStreamClass implements Serializable { public static ObjectStreamClass lookup(Class> cl); public static ObjectStreamClass lookupAny(Class> cl); public String getName(); public long getSerialVersionUID(); public Class> forClass(); public ObjectStreamField[] getFields(); public ObjectStreamField getField(String name); public String toString(); }
The code above shows key methods provided by ObjectStreamClass
.
These methods allow inspection of serialization metadata. The lookup methods are
used to obtain instances of ObjectStreamClass for specific classes.
Getting ObjectStreamClass for a Class
The lookup
method is the primary way to obtain an ObjectStreamClass
instance. It returns the descriptor for a serializable class or null for
non-serializable classes. The lookupAny
method works similarly but
doesn't check serializability.
import java.io.ObjectStreamClass; import java.io.Serializable; class Person implements Serializable { private static final long serialVersionUID = 1L; private String name; private int age; } public class Main { public static void main(String[] args) { // Get ObjectStreamClass for serializable class ObjectStreamClass osc = ObjectStreamClass.lookup(Person.class); System.out.println("Class name: " + osc.getName()); System.out.println("SerialVersionUID: " + osc.getSerialVersionUID()); // Try with non-serializable class ObjectStreamClass osc2 = ObjectStreamClass.lookup(String.class); System.out.println("String class serializable? " + (osc2 != null)); } }
This example demonstrates getting ObjectStreamClass for a serializable class. The Person class implements Serializable and has a serialVersionUID. The lookup method returns null for String class which doesn't implement Serializable.
Inspecting Serialization Metadata
ObjectStreamClass provides methods to inspect serialization metadata. The
getFields
method returns all serializable fields. The
getField
method retrieves a specific field by name.
import java.io.ObjectStreamClass; import java.io.Serializable; class Employee implements Serializable { private static final long serialVersionUID = 2L; private String id; private transient String password; public String department; } public class Main { public static void main(String[] args) { ObjectStreamClass osc = ObjectStreamClass.lookup(Employee.class); System.out.println("Class: " + osc.getName()); System.out.println("SUID: " + osc.getSerialVersionUID()); // Get all serializable fields ObjectStreamField[] fields = osc.getFields(); System.out.println("\nSerializable fields:"); for (ObjectStreamField field : fields) { System.out.println(field.getName() + " - " + field.getType()); } // Get specific field ObjectStreamField deptField = osc.getField("department"); System.out.println("\nDepartment field type: " + deptField.getType()); } }
This example shows how to inspect serialization metadata. The Employee class has three fields, but only two are serializable (transient fields are excluded). The getFields method returns only serializable fields including public ones.
Comparing SerialVersionUID Values
The serialVersionUID is crucial for version compatibility in serialization. ObjectStreamClass can help verify if the runtime class matches the serialized version. Mismatched UIDs cause InvalidClassException during deserialization.
import java.io.ObjectStreamClass; import java.io.Serializable; class Product implements Serializable { private static final long serialVersionUID = 12345L; private String name; private double price; } class ModifiedProduct implements Serializable { private static final long serialVersionUID = 67890L; private String name; private double price; private String category; // Added field } public class Main { public static void main(String[] args) { ObjectStreamClass original = ObjectStreamClass.lookup(Product.class); ObjectStreamClass modified = ObjectStreamClass.lookup(ModifiedProduct.class); System.out.println("Original SUID: " + original.getSerialVersionUID()); System.out.println("Modified SUID: " + modified.getSerialVersionUID()); if (original.getSerialVersionUID() == modified.getSerialVersionUID()) { System.out.println("Classes are compatible"); } else { System.out.println("Classes are incompatible - UIDs differ"); } } }
This example demonstrates checking serialVersionUID compatibility. The Product and ModifiedProduct classes have different UIDs due to structural changes. During deserialization, this mismatch would cause an InvalidClassException.
Working with Arrays
ObjectStreamClass can also describe array classes. The class name follows the JVM array type naming convention. Arrays are always serializable regardless of their component type.
import java.io.ObjectStreamClass; public class Main { public static void main(String[] args) { // Get ObjectStreamClass for various array types ObjectStreamClass intArray = ObjectStreamClass.lookup(int[].class); ObjectStreamClass stringArray = ObjectStreamClass.lookup(String[].class); ObjectStreamClass multiArray = ObjectStreamClass.lookup(int[][].class); System.out.println("int[] class: " + intArray.getName()); System.out.println("String[] class: " + stringArray.getName()); System.out.println("int[][] class: " + multiArray.getName()); // Arrays are always serializable System.out.println("\nIs int[] serializable? " + (intArray != null)); System.out.println("Is String[] serializable? " + (stringArray != null)); } }
This example shows how ObjectStreamClass works with arrays. All array types are serializable, even if their component types aren't. The class names use JVM notation (e.g., "[I" for int[], "[[I" for int[][], "[Ljava.lang.String;" for String[]).
Using lookupAny for Non-Serializable Classes
The lookupAny
method returns ObjectStreamClass for any class,
including non-serializable ones. This can be useful for examining class
structure regardless of serializability.
import java.io.ObjectStreamClass; import java.util.Date; class NonSerializable { private int value; public String info; } public class Main { public static void main(String[] args) { // Using lookup (returns null for non-serializable) ObjectStreamClass osc1 = ObjectStreamClass.lookup(NonSerializable.class); System.out.println("lookup result: " + osc1); // Using lookupAny (works for any class) ObjectStreamClass osc2 = ObjectStreamClass.lookupAny(NonSerializable.class); System.out.println("\nClass from lookupAny: " + osc2.getName()); System.out.println("SUID: " + osc2.getSerialVersionUID()); // Works with serializable classes too ObjectStreamClass osc3 = ObjectStreamClass.lookupAny(Date.class); System.out.println("\nDate class: " + osc3.getName()); } }
This example demonstrates the difference between lookup and lookupAny. The NonSerializable class isn't serializable, so lookup returns null. lookupAny returns an ObjectStreamClass for any class, allowing inspection of its fields and computed serialVersionUID.
Examining Field Descriptors
ObjectStreamField objects provide detailed information about serializable fields. They include field name, type, and whether the field is primitive or not. This metadata is useful for analyzing serialized data structure.
import java.io.ObjectStreamClass; import java.io.ObjectStreamField; import java.io.Serializable; class InventoryItem implements Serializable { private static final long serialVersionUID = 1L; private String sku; private int quantity; private double price; private transient String location; } public class Main { public static void main(String[] args) { ObjectStreamClass osc = ObjectStreamClass.lookup(InventoryItem.class); ObjectStreamField[] fields = osc.getFields(); System.out.println("Serializable fields in InventoryItem:"); for (ObjectStreamField field : fields) { System.out.println("\nField: " + field.getName()); System.out.println("Type: " + field.getType()); System.out.println("Type code: " + field.getTypeCode()); System.out.println("Is primitive: " + field.isPrimitive()); System.out.println("Is unshared: " + field.isUnshared()); } } }
This example examines field descriptors of the InventoryItem class. The transient location field is excluded from serialization. Each ObjectStreamField provides type information and other metadata about serializable fields.
Source
Java ObjectStreamClass Class Documentation
In this article, we've covered the essential methods and features of the Java ObjectStreamClass class. Understanding these concepts is crucial for working with Java's serialization mechanism and versioning of serialized objects.
Author
List all Java tutorials.