What is Java serialization, and what is the role of the Serializable interface and serialVersionUID?
Quick Answer
Serialization converts an object's state into a byte stream (via ObjectOutputStream) that can be stored or transmitted and later reconstructed (via ObjectInputStream) as an equivalent object. A class must implement the Serializable marker interface to be eligible. serialVersionUID is a version identifier embedded in the serialized form; if it's absent, the JVM computes one from the class's structure, so any structural change can silently break deserialization of old data unless a stable, explicit serialVersionUID is declared.
Detailed Answer
Serialization converts an object graph into a byte stream that can be written to a file, sent over a network, or stored, and later reconstructed into an equivalent object via deserialization:
class User implements Serializable {
String name;
int age;
}
try (ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("user.dat"))) {
out.writeObject(new User());
}
try (ObjectInputStream in = new ObjectInputStream(new FileInputStream("user.dat"))) {
User u = (User) in.readObject();
}
A class must implement the Serializable marker interface (no methods to implement — it's purely a signal to ObjectOutputStream, which throws NotSerializableException for a class that doesn't implement it). Every non-transient field must itself be serializable (or primitive), recursively — an object graph with a non-serializable field will fail unless that field is marked transient.
serialVersionUID is a long constant embedded in the serialized bytes, used by ObjectInputStream to verify that the sender's and receiver's class versions are compatible during deserialization:
class User implements Serializable {
private static final long serialVersionUID = 1L; // explicit, stable
String name;
int age;
}
If you don't declare it explicitly, the JVM computes one automatically based on the class's structure (fields, methods, interfaces) — which means an unrelated change (adding a method, reordering fields) can silently change the computed UID, causing InvalidClassException when trying to deserialize data that was serialized by an older version of the class, even if the change was otherwise harmless. Declaring an explicit serialVersionUID avoids this fragility and gives you conscious control over exactly when you intend to break compatibility with previously serialized data.
Given serialization's known security history (deserializing untrusted data has been a major source of RCE vulnerabilities) and its brittleness across versions, many modern systems prefer explicit, versioned formats (JSON, Protocol Buffers) over Java's built-in serialization for anything beyond simple, trusted, same-version use cases like short-lived caching.