Core Java

Singleton Design Pattern – A Lion’s Eye View

A few days ago when I was in my home town, one of my sub-juniors from my colleague attended an interview in an MNC and was severely injured in that interview process. I mean he could not qualify the interview because of the difficult questions fired by the interview panel. When I came back to Bangalore, he shared the embarrassing situation he confronted during the technical interview. Based upon his experience today I am writing this article on the Singleton Design Pattern. By the way my junior colleague has nearly four years of experience in Java. One of the controversial questions he faced was “What is the Singleton Design Pattern and how will you write a robust singleton class?” However let me give you the basic and critical outlines of the Singleton Design Pattern frequently used at the time of project/product development.
 
As you know the Singleton design pattern comes under the category of “Creational Pattern“. The basic principle says there should be one and only one instance of a class at any point of time irrespective of multiple invocations of a class. There are many concepts and designs behind this principle. Many developers assume different ways of implementing Singleton in Java. Some developers do not like this design at all. However we should concentrate on this design and other factors are completely irrelevant for us. Let us analyze this design from various perspectives.

Technicalities

As I have mentioned that there will be one instance of a class, let us see the code below.

 
package com.ddlab.rnd.patterns;
public class SingletonType1 
{
	private static SingletonType1 instance = null;

	private SingletonType1()
	{
		super();
	}

	public static SingletonType1 getInstance()
	{
		if( instance == null )
			instance = new SingletonType1();
		return instance;
	}
}

To use and implement we have to write the following code.

SingletonType1 instance = SingletonType1.getInstance();

It is fine and seems to be correct. If you write the above code 10 times or more you will get the same instance. To check the correctness of the above program. Let us do a basic clinical test. Create the instances of the above class by invoking “SingletonType1.getInstance()” the code and put all the instances in a Set. As you know that Set does not allow duplicates. So at the end if you are getting the size of the set 1, then it is the correct implementation. You can this also. Definitely you will get the result as 1, the size of the Set. Now question comes into our mind, can we break the above design ? Is it possible to create multiple instances of the above defined class ? YES. We can. We can break the above design and we can create multiple instances. How is that ????????

Let us see the code below.

package com.ddlab.rnd.patterns;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;

public class TestSingletonType1 
{
	public void createMultiInstances()
	{
		System.out.println("\n** MULTIPLE INSTANCES FROM SINGLETO **\n");
		/*
		 * Using Reflection you can break singleton
		 */
		try 
		{
			Class clazz = Class.forName("com.ddlab.rnd.patterns.SingletonType1");
			Constructor constructor = clazz.getDeclaredConstructors()[0];
			constructor.setAccessible(true);
			SingletonType1 instance1 = (SingletonType1)constructor.newInstance(null);
			SingletonType1 instance2 = (SingletonType1)constructor.newInstance(null);
			SingletonType1 instance3 = (SingletonType1)constructor.newInstance(null);

			System.out.printf( "%-15s %-15s %n", "SERIAL NO", "MULTI INSTANCES");
			System.out.printf( "%-15s %-15s %n", "---------", "---------------");

			System.out.format("%-15s %-15s %n", "INSTANCE 1 ",instance1);
			System.out.format("%-15s %-15s %n", "INSTANCE 2 ",instance2);
			System.out.format("%-15s %-15s %n", "INSTANCE 3 ",instance3);
		}
		catch (Exception e) 
		{
			e.printStackTrace();
		}
	}

	public void createMultiInstances1()
	{
		System.out.println("\n********* MULTIPLE INSTANCES FROM SINGLETON ********\n");
		/*
		 * Using Reflection you can break singleton
		 */
		try 
		{
			Class clazz = Class.forName("com.ddlab.rnd.patterns.SingletonType1");
			Method method = clazz.getDeclaredMethods()[0];
			Field field = clazz.getDeclaredFields()[0];
			field.setAccessible(true);

			SingletonType1 instance1 = (SingletonType1)method.invoke(clazz, null);
			field.set(clazz, null);
			SingletonType1 instance2 = (SingletonType1)method.invoke(clazz, null);
			field.set(clazz, null);
			SingletonType1 instance3 = (SingletonType1)method.invoke(clazz, null);

			System.out.printf( "%-15s %-15s %n", "SERIAL NO", "MULTI INSTANCES");
			System.out.printf( "%-15s %-15s %n", "---------", "---------------");

			System.out.format("%-15s %-15s %n", "INSTANCE 1 ",instance1);
			System.out.format("%-15s %-15s %n", "INSTANCE 2 ",instance2);
			System.out.format("%-15s %-15s %n", "INSTANCE 3 ",instance3);
		}
		catch (Exception e) 
		{
			e.printStackTrace();
		}
	}

	public void createInstances()
	{
		System.out.println("\n*********** SINGLE INSTANCES FROM SINGLETON ********\n");
		SingletonType1 instance1 = SingletonType1.getInstance();
		SingletonType1 instance2 = SingletonType1.getInstance();
		SingletonType1 instance3 = SingletonType1.getInstance();

		System.out.printf( "%-15s %-15s %n", "SERIAL NO", "INSTANCES");
		System.out.printf( "%-15s %-15s %n", "---------", "----------");

		System.out.format("%-15s %-15s %n", "INSTANCE 1 ",instance1);
		System.out.format("%-15s %-15s %n", "INSTANCE 2 ",instance2);
		System.out.format("%-15s %-15s %n", "INSTANCE 3 ",instance3);
	}

	public static void main(String[] args) 
	{
		new TestSingletonType1().createInstances();
		new TestSingletonType1().createMultiInstances();
		new TestSingletonType1().createMultiInstances1();
	}

}

If you run the above program you will be able to see the many instances of the defined singleton class.

However we got to know to know the private constructor approach of Singleton can be broken using reflection. In the above case we are able to create the instance of a class having private constructor and also we are able to access the private field. Oho… Really… have you really created the multiple instances… Yes BOSS, I have done, what do you think ? You build the design in any manner but I can break. Really it hurts the sentiment of a true emotional developer like me. OKKkkk. Now I will write a very efficient code so that you will not be able to break. Really ……..???????? It is very important to learn java Relection mechanism to explore the beauty of JAVA.

Now let us see how to write a better code so that other developers will not be able to break using reflection.

package com.ddlab.rnd.patterns;
import java.lang.reflect.ReflectPermission;
import java.security.Permission;

public class SingletonType2 
{
	static
	{
		getInstance();
	}
	private static SingletonType2 instance = null;

	private SingletonType2()
	{
		super();
		//Add the following piece of code so that it can not be invoked using relection
		System.setSecurityManager(new SecurityManager() {
            @Override
            public void checkPermission(Permission perm) 
            {
            	if (perm instanceof ReflectPermission )
            	{
            		System.out.println("\nYes I will not allow you to create the instance using Reflection...\n");
            		throw new SecurityException();
            	}
            	else
            	{
            		//Do nothing
            	}
            }

        });
	}

	public static SingletonType2 getInstance()
	{
		if( instance == null )
			instance = new SingletonType2();

		return instance;
	}
}

Now it is true, your reflection attack will not impact the above code. You will get Exception here if you use reflection to create another instance. You can think for while that , it may be broken using java introspection utility. You may also think that , we will not access constructor rather we will access the field and later on we will set the field value as null and again we will invoke the field. It is a good strategy but you will fail as introspection utility is another kind of reflection. Since we do not allow reflection, you will not be able to create multiple instances. However you can still use introspection to invoke the method “getInstance()” but you will get the same instance. So our idea of reflection and introspection can be discarded in this context. Let us think in a different manner, point towards Serialization of the class. So what will happen if we want to serialize ???? In the above class you can not go for inheritance as the constructor is private, for bullet proof mechanism you can make the class final. We can not serialize the class SingletonType2 as it does not implement Serializable interface and also we do not allow reflection. However we can not serialize a class which does not implement Serilizable interface. However sometimes it is required to persist the Singleton object for a day. In this case we have to implement Serializable interface in singleton class. Now our project or product demands Serialization and we will not use SecurityManager concept. Let us modify the above class.

Let us see the Singleton class with Serializable interface.

package com.ddlab.rnd.patterns;
import java.io.Serializable;

public class SingletonType11 implements Serializable
{
	private static final long serialVersionUID = -4137189065490862968L;
	private static SingletonType11 instance = null;

	private SingletonType11()
	{
		super();
	}

	public static SingletonType11 getInstance()
	{
		if( instance == null )
			instance = new SingletonType11();
		return instance;
	}
}

Ok, we will be able to serialize the above class but again we are providing an opportunity to the hacker to create multiple instances and thereby our concept again breaks here. Let us see how we can again break the concept of Singleton through object serialization. Let use write a small class like this.

package com.ddlab.rnd.patterns;
import java.io.Serializable;

public class BreakSingleton implements Serializable 
{
	private static final long serialVersionUID = 5904306999023481976L;

	private SingletonType11 instance2 = SingletonType11.getInstance();

	public SingletonType11 getInstance2() {
		return instance2;
	}

	public void setInstance1(SingletonType11 instance2) {
		this.instance2 = instance2;
	}	
}

Let us see the test harness class for the above.

package com.ddlab.rnd.patterns;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.OutputStream;

public class TestBreakSingleton 
{
	public static void main(String[] args) throws Exception
	{
		BreakSingleton bs = new BreakSingleton();

		OutputStream out = new FileOutputStream("data/a.ser");
		ObjectOutputStream oout = new ObjectOutputStream(out);
		oout.writeObject(bs);
		oout.flush();
		oout.close();
		out.flush();
		out.close();

		InputStream in = new FileInputStream("data/a.ser");
		ObjectInputStream oin = new ObjectInputStream(in);
		BreakSingleton bs1 = (BreakSingleton)oin.readObject();
		oin.close();
		in.close();

		System.out.println("Instance from Serialization :::"+bs1.getInstance2());
		System.out.println("Normal Instance :::"+SingletonType11.getInstance());

		InputStream in1 = new FileInputStream("data/a.ser");
		ObjectInputStream oin1 = new ObjectInputStream(in1);
		BreakSingleton bs2 = (BreakSingleton)oin1.readObject();
		oin1.close();
		in1.close();
		System.out.println("Another Instance from Serialization :::"+bs2.getInstance2());
	}

}

If you run the above program, you will get the following type of output.

Instance from Serialization :::com.ddlab.rnd.patterns.SingletonType11@2586db54

Normal Instance :::com.ddlab.rnd.patterns.SingletonType11@12276af2

Another Instance from Serialization :::com.ddlab.rnd.patterns.SingletonType11@38a97b0b

So now you got three different instances of a Singleton class. Again we are into great problem having the multiple instances. Is there any way so that we will not give chance to the hacker to create multiple instances but we will be able to serialize the object ? Ohhh, yes, there is. Now let us see the modified singleton java class so that we will be able to serialize the object and at any point of time we will get the consistent singleton class.

package com.ddlab.rnd.patterns;
import java.io.ObjectStreamException;
import java.io.Serializable;

public class SingletonType11 implements Serializable
{
	private static final long serialVersionUID = -4137189065490862968L;
	private static SingletonType11 instance = null;

	private SingletonType11()
	{
		super();
	}

	public static SingletonType11 getInstance()
	{
		if( instance == null )
			instance = new SingletonType11();
		return instance;
	}

	private Object readResolve() throws ObjectStreamException
	{
		return instance;
	}

	private Object writeReplace() throws ObjectStreamException
	{
		return instance;
	}
}

In this above approach we will get the consistent singleton object from the serialized object and from the normal invocation of the “getInstance()” method. However still we can create multiple instance using Reflection and we can not prevent reflection as we want to serialize the object. In this case we can make a request and make an agreement to the developers not to use reflection just to avoid reflection strategy. Developers came to an agreement not to break using reflection.

What about multi-threading or the use of singleton in a multi-threaded application ? Let us see what happens here. Let us see the use of thread in case of Singleton class.

Let us consider the first Singleton class we discussed earlier.

 
package com.ddlab.rnd.patterns;
public class SingletonType1 
{
	private static SingletonType1 instance = null;

	private SingletonType1()
	{
		super();
	}

	public static SingletonType1 getInstance()
	{
		if( instance == null )
			instance = new SingletonType1();

		return instance;
	}
}

Basically this approach is called lazy-initialization. In case of multi-threading we can get multiple instances if we do not handle properly. Let see the code below.

 
package com.ddlab.rnd.patterns;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;

class Thread1 extends Thread
{
	@Override
	public void run() 
	{
		SingletonType1 instance = SingletonType1.getInstance();
		//		System.out.println("In Thread 1 - Singleton Instance ---->"+instance);
		TestSingletonType1_Thread.singletonSet.add(instance);
	}
}

class Thread2 extends Thread
{
	@Override
	public void run() 
	{
		SingletonType1 instance = SingletonType1.getInstance();
		//		System.out.println("In Thread 2 - Singleton Instance ---->"+instance);
		TestSingletonType1_Thread.singletonSet.add(instance);
	}
}

Let us see the test class how to use it.

  
public class TestSingletonType1_Thread 
{
	private static Set singletonSet1 = new HashSet();
	public static Set singletonSet = Collections.synchronizedSet(singletonSet1);

	public static void main(String[] args) 
	{
		//Singleton concept is broken here
		for( int i = 0 ; i < 100 ; i++ )
		{
			new Thread1().start();
			new Thread2().start();

			if( singletonSet.size() > 1 )
				break;
			else
				continue;
		}
		System.out.println(singletonSet);
	}
}

If you run the above program many times, you will get the different instances of the Singleton class.

Upon running the program, you may get a similar type result like this. The output is given below.

 [com.ddlab.rnd.patterns.SingletonType1@60723d7c, com.ddlab.rnd.patterns.SingletonType1@6d9efb05, com.ddlab.rnd.patterns.SingletonType1@8dd20f6]

So what to do ? Can we declare volatile variable, let see now. Let us have the modified program.

 
package com.ddlab.rnd.patterns;
public class SingletonType1 
{
	private static volatile SingletonType1 instance = null;

	private SingletonType1()
	{
		super();
	}

	public static SingletonType1 getInstance()
	{
		if( instance == null )
			instance = new SingletonType1();
		return instance;
	}
}

Upon running the program many times , you may get like this.

 [com.ddlab.rnd.patterns.SingletonType1@3f0ef90c, com.ddlab.rnd.patterns.SingletonType1@2e471e30]

However use of volatile does not serve our purpose here. Still the same problem, can we use synchronized method, yes we can do it. In many cases most of the developers ask question related to the usage of volatile keyword and its usage in Singleton. Less experienced developers may be happy if they get the single instance of the above class in the first run in their machine. I have many developers have justified by running this program in their machine and they have also shown to me. It is correct because they are lucky in their first attempt. But I run this program many times in their machine and tell them not forget the truth. Now many of them start modifying the program by using java’s great keyword and life saver “synchronized” . Let us see what happens with this keyword.

Let us see below.

 
package com.ddlab.rnd.patterns;
public class SingletonType1 
{
	private static volatile SingletonType1 instance = null;

	private SingletonType1()
	{
		super();
	}

	public static synchronized SingletonType1 getInstance()
	{
		if( instance == null )
			instance = new SingletonType1();

		return instance;
	}
}

But there will be a performance issue. However, when you analyze it you will realize that synchronization is required only for the first invocation of the method. Subsequent invocations do not require synchronization. So it is not advisable to use the keyword “synchronized” for every invocation. In the long run it may have bitter impact in your product/project development. In order to increase the efficiency of the above program, let use modify the above program in a different manner. We will not synchronize whole method rather we will do the sensitive area.

 
package com.ddlab.rnd.patterns;
public class SingletonType1 
{
	private static volatile SingletonType1 instance = null;

	private SingletonType1()
	{
		super();
	}

	public static SingletonType1 getInstance()
	{
	  if (instance == null)
	  {
		synchronized(SingletonType1.class) {
		  instance = new SingletonType1();
		}
	  }
	  return instance;
	}
}

The above program looks ok and we are happy and let us celebrate now. But still we are far from the bitter reality as there is a very big problem. Two threads can get inside of the if statement concurrently when instance is null. Then, one thread enters the synchronized block to initialize instance, while the other is blocked. When the first thread exits the synchronized block, the waiting thread enters and creates another Singleton object. Note that when the second thread enters the synchronized block, it does not check to see if instance is non-null. Let us do a small clinical test to face the reality.

  
package com.ddlab.rnd.patterns;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;

class Thread11 extends Thread
{
	@Override
	public void run() 
	{
		SingletonType111 instance = SingletonType111.getInstance();
		//		System.out.println("In Thread 1 - Singleton Instance ---->"+instance);
		TestSingletonType111_Thread.singletonSet.add(instance);
	}
}

class Thread22 extends Thread
{
	@Override
	public void run() 
	{
		SingletonType111 instance = SingletonType111.getInstance();
		//		System.out.println("In Thread 2 - Singleton Instance ---->"+instance);
		TestSingletonType111_Thread.singletonSet.add(instance);
	}
}

public class TestSingletonType111_Thread 
{
	private static Set singletonSet1 = new HashSet();
	public static Set singletonSet = Collections.synchronizedSet(singletonSet1);

	public static void main(String[] args) 
	{
		//Singleton concept is broken here
		for( int i = 0 ; i < 100 ; i++ )
		{
			new Thread11().start();
			new Thread22().start();

			if( singletonSet.size() > 1 )
				break;
			else
				continue;
		}
		System.out.println(singletonSet);
	}

}

Now run the above program many times you will get to know. What is to be done next.

Now let us consider another concept called “double-checked locking” which seems to be famous for a set of developers. Many developers apply in many cases and think to be most robust form of singleton.

In software engineering, double-checked locking (also known as “double-checked locking optimization”) is a software design pattern used to reduce the overhead of acquiring a lock by first testing the locking criterion (the “lock hint”) without actually acquiring the lock. Only if the locking

criterion check indicates that locking is required does the actual locking logic proceed. In most of the technical interviews , the technical panel expects this answer from the candidates. If the candidate is able to answer this question as per their taste, the technical panel will be happy and they will select the candidate. Now a days it concept has assumed great importance, but I will say that the technical panel do not have sufficient experience on this concept. Let us analyze it very deeply. The basic structure of the “double check locking ” is given below.

 
public static SingletonType1 getInstance()
{
  if (instance == null)
  {
    synchronized(SingletonType1.class)  // Mark - 1
	{  
      if (instance == null)          // Mark - 2
        instance = new SingletonType1();  // Mark - 3
    }
  }
  return instance;
}

The theory behind double-checked locking is that the second check at // Mark – 2 makes it impossible for two different Singleton objects to be created. Okkkkk…. It may be true for a single threaded application. What about fine grained multi-threaded application ? Let us see the sequence below.

Thread 1 enters the getInstance() method.

Thread 1 enters the synchronized block at // Mark – 1 because instance is null.

Thread 1 is preempted by thread 2.

Thread 2 enters the getInstance() method.

Thread 2 attempts to acquire the lock at // Mark – 1 because instance is still null. However, because thread 1 holds the lock, thread 2 blocks at // Mark – 1.

Thread 2 is preempted by thread 1.

Thread 1 executes and because instance is still null at // Mark – 2, creates a Singleton object and assigns its reference to instance.

Thread 1 exits the synchronized block and returns instance from the getInstance() method.

Thread 1 is preempted by thread 2.

Thread 2 acquires the lock at // Mark – 1 and checks to see if instance is null.

Because instance is non-null, a second Singleton object is not created and the one created by thread 1 is returned. The theory behind double-checked locking is perfect. Unfortunately, reality is entirely different. The problem with double-checked locking is that there is no guarantee it will work on single or multiprocessor machines. The issue of the failure of double-checked locking is not due to implementation bugs in JVMs but to the current Java platform memory model. The memory model allows what is known as “out-of-order writes” and is a prime reason why this idiom fails. However the concept “out-of-order writes” is beyond the scope of our discussion. The bottom line is that double-checked locking, in whatever form, should not be used because you cannot guarantee that it will work on any JVM implementation. As we have seen that although “double-checked-locking” may work but it may fail unexpectedly. What is the solution ?

The solution of Bill Pugh

(An Extract from Wikipedia), University of Maryland Computer Science researcher Bill Pugh has written about the code issues underlying the Singleton pattern when implemented in Java. Pugh’s efforts on the “Double-checked locking” idiom led to changes in the Java memory model in Java 5 and to what is generally regarded as the standard method to implement Singletons in Java. The technique known as the initialization on demand holder idiom, is as lazy as possible, and works in all known versions of Java. It takes advantage of language guarantees about class initialization, and will therefore work correctly in all Java-compliant compilers and virtual machines. The nested class is referenced no earlier (and therefore loaded no earlier by the class loader) than the moment that getInstance() is called. Thus, this solution is thread-safe without requiring special language constructs (i.e. volatile or synchronized).

public class Singleton 
{
        // Private constructor prevents instantiation from other classes
        private Singleton() { }

        /**
        * SingletonHolder is loaded on the first execution of Singleton.getInstance() 
        * or the first access to SingletonHolder.INSTANCE, not before.
        */
        private static class SingletonHolder { 
                public static final Singleton INSTANCE = new Singleton();
        }

        public static Singleton getInstance() {
                return SingletonHolder.INSTANCE;
        }
}

The above is called “Initialization-on-demand holder idiom“. The above structure of Singleton design is the robust in case of highly multi threaded applications. Let us understand the concept in detail. Let us consider a below small example.

public class Something 
{
        private Something() 
       {
        }

        private static class LazyHolder
       {
                public static final Something INSTANCE = new Something();
        }

        public static Something getInstance() 
       {
                return LazyHolder.INSTANCE;
        }
}

How it works

The implementation relies on the well-specified initialization phase of execution within the Java Virtual Machine (JVM); see section 12.4 of Java Language Specification (JLS) for details. When the class Something is loaded by the JVM, the class goes through initialization. Since the class does not have any static variables to initialize, the initialization completes trivially. The static class definition LazyHolder within it is not initialized until the JVM determines that LazyHolder must be executed. The static class LazyHolder is only executed when the static method getInstance is invoked on the class Something, and the first time this happens the JVM will load and initialize the LazyHolder class. The initialization of the LazyHolder class results in static variable INSTANCE being initialized by executing the (private) constructor for the outer class Something. Since the class initialization phase is guaranteed by the JLS to be serial, i.e., non-concurrent, no further synchronization is required in the static getInstance method during loading and initialization. And since the initialization phase writes the static variable INSTANCE in a serial operation, all subsequent concurrent invocations of the getInstance will return the same correctly initialized INSTANCE without incurring any additional synchronization overhead.

However using the concept of “Initialization-on-demand holder idiom” pattern we can achieve a thread-safe singleton construct. Again the question arises, can we break reflectively. Yes we can break the above concept using java reflection mechanism which I have already mentioned. Now question comes , is there any other approach to build a proper singleton design approach. Yes there is another one as suggested by Joshua Bloch(Chief Technical Architect, Google Innovation Lab and Author of famous Book Effective Java).

 
package com.ddlab.rnd.patterns;
public enum SingletonType3 
{
	INSTANCE;
	public void doSomething(String arg) 
	{
		//... perform operation here ...
	}
}

This is the only robust approach of creating a singleton class which is serializable and completely thread-safe as enums by default thread-safe. What about reflection, using our above normal approach of reflection, you can not break singleton object as it has no constructor. What about serialization, you will be able to serialize it but you will get the same instance every time. So finally we have to imbibe this modern approach of creation of Singleton design class. However many developers do not know about it.

However most of the interviewers will not accept the above two approaches because for them it may be a new concept. You can make an argument based upon the JLS and reference to the books. Everyday some of my juniors , colleagues and friends complain that at the time of interview this is most difficult question they normally face at the time of interview. Whatever manner they answer the question, interviewer never get satisfied, it is because most of them do not know the approach of enum in case of singleton design class. If you are also facing the same problem, give the example of Joshua Bloch. you may encounter the question from some developers or interviewers that “Singleton class must have a private constructor and there should be a method called getInstance()”. You have to make an argument that the underline statement is wrong and it is not a protocol or any kind of rule of thumb. It is just an approach which we have adopted over a period of time. The main concept behind singleton is at any point of time, there should be only one instance does not matter how you write the code. If interview constantly make argument with you, you ask him where is the problem in defining enum as an approach for singleton. The timid interviewer may put some non-sense argument. Finally you tell him, in JDK 5, enum was written by Josh Bloch and Neal Gafter. If the developer or interviewer has the guts he can send a mail to these great architects. If the arrogant interviewer stills makes false argument then teach him a lesson that “Sir, you tell me the approach of singleton, which can not be be broken. At least I will break your Singleton design in various manner.”

Still we can not break the above approach of singleton using enum, but we can crack the above by writing a code to create more than one instance. The code is given below do not use the below code for your commercial product. It is a nasty approach of breaking singleton. Let us see the code below.

package com.ddlab.rnd.patterns;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.util.HashSet;
import java.util.Set;
import sun.reflect.ConstructorAccessor;

public class CrackEnumSingleton 
{
	public static void main(String[] args)
	{
		Set set = new HashSet();
		try 
		{
			SingletonType3 firstInstance = SingletonType3.INSTANCE;
			System.out.println(firstInstance.getClass() + " " + firstInstance + " = " + System.identityHashCode(firstInstance));
			set.add(firstInstance);

			Constructor constructor = SingletonType3.class.getDeclaredConstructors()[0];
			Method acquire = constructor.getClass().getDeclaredMethod("acquireConstructorAccessor");//"acquireConstructorAccessor" fields for cracking
			acquire.setAccessible(true);
			acquire.invoke(constructor);

			Method get = constructor.getClass().getDeclaredMethod("getConstructorAccessor");//"getConstructorAccessor" fields for cracking
			get.setAccessible(true);
			ConstructorAccessor invoke = (ConstructorAccessor) get.invoke(constructor);
			Object secondInstance = invoke.newInstance(new Object[] {null,1});
			System.out.println(secondInstance.getClass() + " " + secondInstance + " = " + System.identityHashCode(secondInstance));
			set.add(secondInstance);

			System.out.println("Total No of Singletons :::"+set.size());
		}
		catch (Exception e) 
		{
			e.printStackTrace();
		}
	}

}

However the above approach is just a technique to learn but not to implement anywhere. In this world every object has a positive and a negative approach but we have to follow the positive approach for the smooth development of our product or project.

Conclusion

This article does not bean any commercial significance. In this article I have just provided a better approach of writing a better Singleton design class. There may be best approaches, if you know any other best approaches or best practices, please share with me. Also provide some comments so that we can make better contributions towards a better coding standard. I hope you will enjoy my article. In case of any error please report me at debadatta.mishra@gmail.com. Thank you.
 

Reference: Singleton Design Pattern – A Lion’s Eye View from our JCG partner Debadatta Mishra at the Debadatta Mishra blog.

Debadatta Mishra

I am working as a Technical Architect at JDA Software. I have more than 7 years of industrial experience in the field of Java, XML, Web services, Cloud and Banking and Financial and Logistics domain. I have contributed many articles on Java in internet sites.
Subscribe
Notify of
guest

This site uses Akismet to reduce spam. Learn how your comment data is processed.

5 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
Károly Török
Károly Török
10 years ago

Hmm…I’m left behind the “initialization-on-demand” approach. Im thankful to you sharing this new approach.

Zaptac
Zaptac
10 years ago
ERKAN YALÇIN
ERKAN YALÇIN
9 years ago
Reply to  Zaptac

You can use enums but enums comes into with Java 1.5 ,
You can find more about singleton pattern at this adress http://javacodetips.blogspot.com/2014/04/design-patterns-singleton-pattern.html

Sanket Mishra
Sanket Mishra
9 years ago

Highly informative.. Covering almost all the cases…

Ranjan
Ranjan
8 years ago

In Banking domain, where can we use singleton ? please sir kindly reply.

Back to top button