Preserve Singleton identity across Java serialization boundaries and understand when serialization reveals that the pattern choice is too fragile.
Serialization hazard: A risk that converting an object to bytes and back will create a new instance that breaks the singleton guarantee.
Ordinary class-based singleton implementations can be broken by serialization if deserialization constructs a fresh object instance. That means the pattern’s identity guarantee may silently fail at exactly the boundary where object identity is hardest to inspect.
If a singleton class implements Serializable, default deserialization can create another instance unless you explicitly restore the canonical one.
1private Object readResolve() {
2 return getInstance();
3}
readResolve() tells the deserialization process to replace the deserialized object with the existing singleton instance.
Enum-based singletons are attractive partly because enum serialization is handled specially by the JVM. That removes one of the easiest ways to violate singleton identity.
This is one reason enum singletons are often recommended over hand-rolled class variants.
If singleton identity is that fragile across process or storage boundaries, step back and ask whether the object should really be a singleton at all.
Often the better design is:
Trying to serialize and revive a supposedly unique runtime object is often a sign that lifecycle boundaries are blurred.
When reviewing singleton serialization, ask:
readResolve() present where needed?Serialization bugs are useful because they reveal whether the singleton identity is truly part of the domain or just part of the local runtime arrangement.