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
Share

You may also like...

Leave a Reply

Your email address will not be published. Required fields are marked *