🧠 What’s a Singleton?
A Singleton ensures that a class has only one instance in the JVM:
public class Singleton implements Serializable {
private static final Singleton INSTANCE = new Singleton();
private Singleton() {}
public static Singleton getInstance() {
return INSTANCE;
}
}
✅ So when you do:
Singleton s1 = Singleton.getInstance();
Singleton s2 = Singleton.getInstance();
System.out.println(s1 == s2); // true ✅
💥 Problem: Serialization Can Break It!
When you serialize and deserialize a Singleton:
ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("singleton.ser"));
out.writeObject(Singleton.getInstance());
out.close();
ObjectInputStream in = new ObjectInputStream(new FileInputStream("singleton.ser"));
Singleton deserialized = (Singleton) in.readObject();
Now:
System.out.println(Singleton.getInstance() == deserialized); // ❌ false
❗ Why?
Because
readObject()
creates a new instance in memory.
So now you have two different instances — the singleton is broken.
✅ The Fix: Use readResolve()
To restore the singleton identity after deserialization, implement a method called readResolve()
:
private Object readResolve() throws ObjectStreamException {
return getInstance(); // Return the original singleton
}
Java will automatically call this after readObject()
— and replace the newly created object with the return value of readResolve()
.
🧪 Complete Fixed Example
public class Singleton implements Serializable {
private static final long serialVersionUID = 1L;
private static final Singleton INSTANCE = new Singleton();
private Singleton() {}
public static Singleton getInstance() {
return INSTANCE;
}
private Object readResolve() throws ObjectStreamException {
return INSTANCE;
}
}
Now this works:
Singleton s1 = Singleton.getInstance();
Singleton s2 = deserializeFromFile();
System.out.println(s1 == s2); // ✅ true
🧵 TL;DR
Problem | Explanation |
---|---|
readObject() creates a new instance | Singleton broken |
Result | singleton != deserialized |
Fix | Add readResolve() to return the singleton |
Best practice | Always include readResolve() in serializable Singletons |