In my previous post, I explained what is singleton design pattern is, how to restrict a class to construct only one object. I
request you to go through the post, if you don't know about singleton design
pattern. In this post I am going to explain how serialization breaks the
singleton design pattern.
What is
Serialization?
Serialization is the process of converting object
state into sequence of bytes so that it can be persisted in memory, we can
transfer this persisted state of object across network.
What is
deserialization?
Deserialization is the process of converting the
bytes of data to an object.
Let me show you simple example of singleton class.
class SingleTon { static SingleTon instance = null; private SingleTon() { } public static SingleTon getInstance() { if (instance == null) { synchronized (SingleTon.class) { if (instance == null) { instance = new SingleTon(); } } } return instance; } }
public class TestSingleton { public static void main(String args[]) { SingleTon obj1 = SingleTon.getInstance(); SingleTon obj2 = SingleTon.getInstance(); SingleTon obj3 = SingleTon.getInstance(); System.out.println(obj1); System.out.println(obj2); System.out.println(obj3); } }
Output
SingleTon@7852e922 SingleTon@7852e922 SingleTon@7852e922
As you observe the output, you are always getting
same reference.
Now let me add serialization functionality to the
class SingleTon.
import java.io.Serializable; class SingleTon implements Serializable { private static final long serialVersionUID = 1L; static SingleTon instance = null; private SingleTon() { } public static SingleTon getInstance() { if (instance == null) { synchronized (SingleTon.class) { if (instance == null) { instance = new SingleTon(); } } } return instance; } }
Now update TestSingleton
class like below.
a.
get the
singleton object
b.
Serialize the
object to a file.
c.
Deserialize
the object and check whether you are getting same or not.
import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; public class TestSingleton { private static ObjectInputStream in; private static ObjectOutputStream out; public static void main(String args[]) throws Exception { /* Serialize object */ FileOutputStream fos = new FileOutputStream("ser.out"); out = new ObjectOutputStream(fos); SingleTon obj1 = SingleTon.getInstance(); out.writeObject(obj1); /* Deserialize object */ FileInputStream fis = new FileInputStream("ser.out"); in = new ObjectInputStream(fis); SingleTon obj2 = (SingleTon) in.readObject(); /* Deserialize object */ fis = new FileInputStream("ser.out"); in = new ObjectInputStream(fis); SingleTon obj3 = (SingleTon) in.readObject(); System.out.println(obj1); System.out.println(obj2); System.out.println(obj3); } }
Output
SingleTon@3d4eac69 SingleTon@1b28cdfa SingleTon@eed1f14
As you see the output, I can able to create more
than one object for singleton class.
How to
get rid of this behavior?
To make singleton pattern works properly, Singleton
class must implement the method readResolve. By using readResolve method, you
can control what object should be returned on deserialization. Update Singleton
class like below.
import java.io.Serializable; class SingleTon implements Serializable { private static final long serialVersionUID = 1L; static SingleTon instance = null; private SingleTon() { } public static SingleTon getInstance() { if (instance == null) { synchronized (SingleTon.class) { if (instance == null) { instance = new SingleTon(); } } } return instance; } private Object readResolve() { return instance; } }
Re run TestSingleton
class. You will get following kind of output.
SingleTon@3d4eac69 SingleTon@3d4eac69 SingleTon@3d4eac69
You may like
No comments:
Post a Comment