What is Java serialization, and what is the role of the Serializable interface and serialVersionUID?

8 minintermediateserializationserializableserialversionuid

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. It's 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. It has 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. ObjectInputStream uses it 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. That means an unrelated change, like adding a method or reordering fields, can silently change the computed UID. This causes InvalidClassException when deserializing 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 like JSON or Protocol Buffers over Java's built-in serialization. Java serialization is best kept to simple, trusted, same-version use cases, like short-lived caching.