Code Pumpkin

Serialization and Singleton Design Pattern

This is our forth article in the series of Singleton Design Pattern Articles. The purpose of the singleton class is to control object creation, limiting the number of objects to only one. 

In our previous three articles, we have discussed how we can create Singleton Design Pattern in Single-threaded and multithreaded environment. We have also discussed how we can prevent object cloning if our Singleton class is Cloneable.


Serializable Singleton

Sometimes in distributed systems, we are required to store state of java objects in file system and retrieve it later point of time. To achieve this, Java provides built in Serialization mechanism. Basic requirement to mark our class as Serializable is to implement Serializable marker interface. 

Let's make our Singleton class Serializable. For Simplicity I am using Eager Initialization Approach for the demo.

import java.io.Serializable;

public class SerializableSingleton implements Serializable{

		private static SerializableSingleton instance = new SerializableSingleton();

		private SerializableSingleton() {
			System.out.println("Constructor is being called");
		}

		public static SerializableSingleton getInstance() {
			return instance;
		}
}

Let’s test our singleton class whether it maintains single instance after serializable and deserializable operations?

public static void main(String args[]) {

	try {
		SerializableSingleton instance1 = SerializableSingleton.getInstance();
		ObjectOutput out = null;

		// Serialize object state to file
		out = new ObjectOutputStream(new FileOutputStream("codePumpkin.ser"));
		out.writeObject(instance1);
		out.close();

		// deserialize from file to object
		ObjectInput in = new ObjectInputStream(new FileInputStream("codePumpkin.ser"));
		SerializableSingleton instance2 = (SerializableSingleton) in.readObject();
		in.close();

		System.out.println("instance1 hashCode = " + instance1.hashCode());
		System.out.println("instance2 hashCode = " + instance2.hashCode());

	} catch (IOException | ClassNotFoundException e) {
		e.printStackTrace();
	}

}

Output

instance1 hashCode = 118352462
instance2 hashCode = 1406718218

readResolve() method

We can see that the hash code of both the instances are different in above example. That clearly violates singleton principle. The problem with above serialized singleton class is that whenever we deserialize it, it will create a new instance of the class. We can prevent this by providing implementation readResolve() method as shown below. 

protected Object readResolve() {
      return getInstance();
}

During serialization process readObject() is used to create instance and it creates new instance every time we deserialize the Singleton object. But we can replace that newly created instance in the stream with our original Singleton instance using readResolve().  No reference to the newly created instance is retained, so it immediately becomes eligible for garbage collection. 


transient fields

If we are depending on readResolve() method, we must declare all instance fields with object reference types as transient. Otherwise, it is possible for a determined attacker to secure a reference to the deserialized object before its readResolve() method is run.

You can read more about How attacker can break the singleton pattern if fields are not transient in chapter 77 of Joshua Bloch's Effective Java 2nd Edition. Here is the summary of that chapter : 

The attack is a bit complicated, but the underlying idea is simple. If a singleton contains a non-transient object reference field, the contents of this field will be deserialized before the singleton’s readResolve() method is run. This allows a carefully crafted stream to “steal” a reference to the originally deserialized singleton at the time the contents of the object reference field are deserialized.


Additional Serialization Care

Along with readResolve() method implementation, we should also declare serialVersionUID in our Singleton class. This is just a good practice and not mandatory for achieving Serializable Singleton.

Here is the complete Java Program code for Serializable Singleton:

import java.io.*;

public class SerializableSingleton implements Serializable {
	
	
	private static final long serialVersionUID = 1L;
	private static SerializableSingleton instance = new SerializableSingleton();
	
	// make additional fields transient
	transient String[] xyz = {"xyz1", "xyz2", "xyz3"};

	private SerializableSingleton() {
	}

	public static SerializableSingleton getInstance() {
		return instance;
	}
	
	protected Object readResolve() {
      return getInstance();
	}
}

Download Complete Java Program »


If Singleton class has not implemented Serialiable interface, then Java will give NotSerializableException when some attacker will try to serialize Singleton object. In other words, if we have not implemented Serializable interface, we do not require to worry about all these attacks at all.

Then, Why do we need to make our Singleton class Serializable?

Well it is not at all required.  There is no useful real world scenario where we require to Serialize Singleton Object. A singleton usually doesn't change of state throughout its lifetime nor contains any state which we can save/restore. If it does, then it is already wrong to make it a singleton.

Java SE API contains two Singleton implementations

  1. java.lang.Runtime and 
  2. java.awt.Desktop

​None of them implements serializable. It also doesn't make any sense as well.


However, here is one case where we may require to handle Serialization while implementing Singleton Design Pattern.

What if super class has implemented Serialization interface?

If our Singleton class is required to inherit all the properties of some class i.e. ParentClass and that class is Serializable. For Example,

class ParentClass implements Serializable{
	
}
public class SerializableSingleton extends ParentClass {
	 // Singleton Code
}

Well in this case, we need to take all the preventive actions like make all the fields transient and provide readResolve() method implementation.

There is also one more approach to handle this scenario. Override writeObject() method and throw  NotSerializableException from it.  It will behave same as you have not implemented Serializable interface.


Next Article in the series of Singleton Design Pattern :  Breaking Singleton using reflection and Enum Singleton

Liked this article? Take a second to support CodePumpkin on Patreon!

Tags: , , , , , , ,


Comments and Queries

If you want someone to read your code, please put the code inside <pre><code> and </code></pre> tags. For example:
<pre><code class="java"> 
String foo = "bar";
</code></pre>
For more information on supported HTML tags in disqus comment, click here.
Contribute Your Articles

Interview Experiences

Subscribe Us

Like Us On Facebook

Support Code Pumpkin on Patreon!