On this page
Serialization
Serialization converts a Java object into a byte stream for storage or transmission. Deserialization reconstructs the object from bytes.
Basic Serialization
Implement java.io.Serializable (a marker interface):
public class User implements Serializable {
private static final long serialVersionUID = 1L;
private String name;
private int age;
private transient String password; // excluded from serialization
public User(String name, int age, String password) {
this.name = name;
this.age = age;
this.password = password;
}
}
Writing and Reading Objects
User user = new User("Alice", 30, "secret");
// Serialize
try (ObjectOutputStream oos = new ObjectOutputStream(
new FileOutputStream("user.ser"))) {
oos.writeObject(user);
}
// Deserialize
try (ObjectInputStream ois = new ObjectInputStream(
new FileInputStream("user.ser"))) {
User restored = (User) ois.readObject();
System.out.println(restored.getName()); // Alice
// restored.password is null (transient)
}
serialVersionUID
Every serializable class should declare a serialVersionUID:
private static final long serialVersionUID = 1L;
If the class structure changes without updating the UID, deserialization throws InvalidClassException. Increment the UID when making incompatible changes.
transient Keyword
Fields marked transient are skipped during serialization:
- Passwords and secrets
- Derived/computed fields
- Non-serializable objects
Externalizable Interface
For full control over serialization format, implement Externalizable:
public class Product implements Externalizable {
private String name;
private double price;
public Product() { } // public no-arg constructor required
@Override
public void writeExternal(ObjectOutput out) throws IOException {
out.writeUTF(name);
out.writeDouble(price);
}
@Override
public void readExternal(ObjectInput in) throws IOException {
name = in.readUTF();
price = in.readDouble();
}
}
Unlike Serializable, Externalizable requires you to explicitly read and write every field.
Serialization Rules
What gets serialized:
- Non-transient, non-static instance fields of serializable classes
- Object graphs (referenced objects must also be serializable)
What does not get serialized:
staticfieldstransientfields- Fields of non-serializable types (throws
NotSerializableException)
Custom Serialization
public class Order implements Serializable {
private static final long serialVersionUID = 1L;
private List<Item> items;
private void writeObject(ObjectOutputStream out) throws IOException {
out.defaultWriteObject();
// custom logic
}
private void readObject(ObjectInputStream in)
throws IOException, ClassNotFoundException {
in.defaultReadObject();
// custom logic
}
}
Security Concerns
Java serialization has known security vulnerabilities (deserialization attacks):
- Do not deserialize untrusted data
- Prefer JSON, Protocol Buffers, or other formats for external data exchange
- Use
ObjectInputFilter(Java 9+) to restrict deserializable classes:
ObjectInputStream ois = new ObjectInputStream(input);
ois.setObjectInputFilter(
ObjectInputFilter.Config.createFilter("com.myapp.*;!*"));
Modern Alternatives
| Format | Use Case |
|---|---|
| JSON (Jackson, Gson) | REST APIs, config files |
| Protocol Buffers | High-performance RPC |
| Java Records + JSON | Simple DTOs |
Best Practices
- Always declare
serialVersionUID - Mark sensitive and non-serializable fields as
transient - Avoid Java serialization for external/untrusted data
- Consider JSON or Protobuf for new projects
- Keep serializable classes simple — prefer composition over deep object graphs