Singleton Invalidated by Serialization
When we serialize an object and deserialize it again there are different hash code values generated as shown in the example below. So our Singleton principle breaks in case of object serialization/deserialization.
package com.loopandbreak.singleton; import java.io.*; /** * This class will implement basic Singleton design pattern */ public class SingletonPatternInvalidatedBySerialization implements Serializable { private static SingletonPatternInvalidatedBySerialization singletonPattern = new SingletonPatternInvalidatedBySerialization(); /* * Constructor is made private */ private SingletonPatternInvalidatedBySerialization() { System.out.println("Creating Object....."); } public static SingletonPatternInvalidatedBySerialization getInstance() { return singletonPattern; } public static void main(String[] args) throws IOException, ClassNotFoundException { SingletonPatternInvalidatedBySerialization object1 = SingletonPatternInvalidatedBySerialization.getInstance(); SingletonPatternInvalidatedBySerialization object2 = SingletonPatternInvalidatedBySerialization.getInstance(); print(object1); print(object2); // Serialize ObjectOutputStream objectOutputStream = new ObjectOutputStream(new FileOutputStream("D:/object2.ser")); objectOutputStream.writeObject(object2); // Deserialize ObjectInputStream objectInputStream = new ObjectInputStream(new FileInputStream("D:/object2.ser")); SingletonPatternInvalidatedBySerialization object3 = (SingletonPatternInvalidatedBySerialization) objectInputStream.readObject(); print(object3); } private static void print(SingletonPatternInvalidatedBySerialization object) { System.out.println("Hashcode of object is " + object.hashCode()); } }
Output
Creating Object..... Hashcode of object is 460141958 Hashcode of object is 460141958 Hashcode of object is 2133927002
How to Fix: Implement readResolve() method in the Singleton class.
readResolve()
The readResolve method is called when ObjectInputStream has read an object from the stream and is preparing to return it to the caller. ObjectInputStream checks whether the class of the object defines the readResolve method. If the method is defined, the readResolve method is called to allow the object in the stream to designate the object to be returned. The object returned should be of a type that is compatible with all uses. If it is not compatible, a ClassCastException will be thrown when the type mismatch is discovered.
Example
package com.loopandbreak.singleton; import java.io.*; /** * This class will implement basic Singleton design pattern */ public class SingletonPatternInvalidatedBySerialization implements Serializable { private static SingletonPatternInvalidatedBySerialization singletonPattern = new SingletonPatternInvalidatedBySerialization(); /* * Constructor is made private */ private SingletonPatternInvalidatedBySerialization() { System.out.println("Creating Object....."); } public static SingletonPatternInvalidatedBySerialization getInstance() { return singletonPattern; } public Object readResolve() { System.out.println("Applying Read Resolve..."); return singletonPattern; } public static void main(String[] args) throws IOException, ClassNotFoundException { SingletonPatternInvalidatedBySerialization object1 = SingletonPatternInvalidatedBySerialization.getInstance(); SingletonPatternInvalidatedBySerialization object2 = SingletonPatternInvalidatedBySerialization.getInstance(); print(object1); print(object2); // Serialize ObjectOutputStream objectOutputStream = new ObjectOutputStream(new FileOutputStream("D:/object2.ser")); objectOutputStream.writeObject(object2); // Deserialize ObjectInputStream objectInputStream = new ObjectInputStream(new FileInputStream("D:/object2.ser")); SingletonPatternInvalidatedBySerialization object3 = (SingletonPatternInvalidatedBySerialization) objectInputStream.readObject(); print(object3); } private static void print(SingletonPatternInvalidatedBySerialization object) { System.out.println("Hashcode of object is " + object.hashCode()); } }
Output
Creating Object..... Hashcode of object is 460141958 Hashcode of object is 460141958 Applying Read Resolve... Hashcode of object is 460141958