Code Pumpkin

Breaking Singleton using reflection and Enum Singleton

January 14, 2018
Posted by Abhi Andhariya

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

In our previous articles, we have discussed how we can create Singleton Design Pattern in Single-threaded and multithreaded environment. We have also discussed how we can Singleton class in case of Searialization and cloning.

In this article, we will discuss how we can break Singleton pattern using Reflection API. We will also understand why Enum Singleton are better than all other implementations?

For navigating to the other articles on Singleton Design Pattern, please refer above table of contents.


Breaking Singleton Using Reflection API

Reflection is an API which is used to examine or modify the behavior of methods, classes, interfaces at runtime for Example,

  1. We can get list of all the public or private methods of the class
  2. We can also change the access levels of the methods, constructor or fields i.e. from private to public or public to private.

How Do you implement basic Singleton Class?

  1. Provide only private constructor,  so that nobody can explicitly create object of our class (Also read  What is the use of private constructor in java?)
  2. Create one instance using private constructor and store it in private static variable.
  3. Provide one public static method.

How can we break the Singleton implementation using reflection?

  1. Use Reflection API to change access level of constructor from private to public using below method:

 AccessibleObject.setAccessible(true)

  1. Instantiate the class as many times as you want using this public constructor.

Java Program Implementation


import java.lang.reflect.Constructor;

public class ReflectionSingletonDemo {

	public static void main(String[] args) {
		ReflectionSingleton instanceOne = ReflectionSingleton.getInstance();
		ReflectionSingleton instanceTwo = null;
		try {
            // Below code will change constructor access level from private to public
			Constructor constructor = ReflectionSingleton.class.getDeclaredConstructor();
            constructor.setAccessible(true);
			
			// Creating second instance
			instanceTwo = (ReflectionSingleton) constructor.newInstance();

		} catch (Exception e) {
			e.printStackTrace();
		}
		System.out.println("instanceOne HashCode : " + instanceOne.hashCode());
		System.out.println("instanceTwo HashCode : " + instanceTwo.hashCode());

	}

}

class ReflectionSingleton {
	private static ReflectionSingleton instance = new ReflectionSingleton();

	private ReflectionSingleton() {

	}

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

Output


instanceOne HashCode : 366712642
instanceTwo HashCode : 1829164700

We can see that the hash code of both the instances are different in above example. That clearly violates singleton principle.


How to prevent Reflection API from breaking Singleton

There are many techniques to prevent such reflection attacks. One of them is throwing an exception in the constructor if it is asked to create second instance.

In other words, Any client attempting to illegally execute the constructor after an instance is created will be thrown an exception.  here is the java program code for the same :


private ReflectionSingleton() {
	if (instance != null) {
	  throw new IllegalStateException("instance already created.");
	}
	System.out.println("Singleton instance is being created.");
}

Replace the above constructor code and re-run the program. It will give you run time exception and prevent creation of second instance. Bingo..!!

However, we can not use this technique with lazy initialization approach. But who cares? we have successfully prevented Reflection API from breaking our Singleton Design Pattern.

Are you Sure? Is there any more loopholes in above code?

What if I change access level of the instance field from private to public and set it to null every time object gets created. It will allow me to create as many objects as I want. Have a look at below code :


import java.lang.reflect.Constructor;
import java.lang.reflect.Field;

public class ReflectionSingletonDemo {

	public static void main(String[] args) {
		ReflectionSingleton instanceOne = ReflectionSingleton.getInstance();
		ReflectionSingleton instanceTwo = null;
		try {

			// Change the access level of private field 'instance' and set null
			// every time object gets created
			Field instance = ReflectionSingleton.class.getDeclaredField("instance");
			instance.setAccessible(true);
			instance.set(instance, null);

			Constructor constructor = ReflectionSingleton.class.getDeclaredConstructor();
			// Below code will change constructor access level from private to
			// public
			constructor.setAccessible(true);

			// Creating second instance
			instanceTwo = (ReflectionSingleton) constructor.newInstance();

		} catch (Exception e) {
			e.printStackTrace();
		}
		System.out.println("instanceOne HashCode : " + instanceOne.hashCode());
		System.out.println("instanceTwo HashCode : " + instanceTwo.hashCode());

	}

}

class ReflectionSingleton {
	private static ReflectionSingleton instance = new ReflectionSingleton();

	private ReflectionSingleton() {
		if (instance != null) {
			throw new IllegalStateException("instance already created.");
		}
		System.out.println("Singleton instance is being created.");
	}

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

Output:


Singleton instance is being created.
Singleton instance is being created.
instanceOne HashCode : 2018699554
instanceTwo HashCode : 1311053135

How can we prevent this?

Our problem is attacker is changing the value of instance field from not-null to null, once object gets created. How can we prevent this? It's very simple. Declare instance as a final so that its value can not be changed once assigned.


private final static ReflectionSingleton instance = new ReflectionSingleton();

Download Complete Java Program »

Good news here is, Reflection API can not convert final field to non-final field. But again this approach only works with eager initialization.


Enum Singleton

Our ReflectionSingleton class is very simple and compact, but in real world applications, Singleton classes will be much more complex. Preventing Reflection attacks are very difficult over there.

To overcome this situation with Reflection, Joshua Bloch suggests the use of Enum to implement Singleton design pattern as Java ensures that any enum value is instantiated only once in a Java program.

Java Program Implementation


public class EnumSingletonDemo {

	public static void main(String[] args) {
		System.out.println(SingletonEnum.INSTANCE);
	}
}

enum SingletonEnum{
	INSTANCE;
	SingletonEnum()
	{
		System.out.println("SingletonEnum Constructor ");
	}
}

Download Complete Java Program »

OutPut 


SingletonEnum Constructor 
INSTANCE

We cannot manually invoke enum constructor from Java Program. JVM handles the creation and invocation of enum constructors internally.

As it is not possible to call enum constructor from the program, it is not possible for us to access them by Reflection also. Hence, reflection can’t break singleton property in case of enums.

Enum Singleton cannot be broken using Serialization and Enums are also by default thread-safe. That makes Enum a good choice for implementint Singleton Design Pattern.


Why Enum is a good choice for Singleton Pattern, why not the best?

By now, you must have heard multiple times that Enums are the best choice for implementing Singleton DP. Are they really?

Well, in our first article we mentioned that every approach has its pros and cons and so do enum. Here are some of the cons of Enum Singleton :

  1. enums do not support lazy loading.
  2. If you are changing design of your application and now you want to convert your singleton class to multi-ton (class which can have multiple objects upto some limit), then enum would not allow this.

If you don't have any problem with above two disadvantages, then enums are the best choice for Singleton.

That's all for this topic. If you guys have any suggestions or queries, feel free to drop a comment. We would be happy to add that in our post. You can also contribute your articles by creating contributor account here.

Happy Learning 🙂

Abhi Andhariya

Surviving Java Developer, Passionate Blogger, Table Tennis Lover, Bookworm, Occasional illustrator and a big fan of Joey Tribbiani, The Walking Dead and Game of Thrones...!!

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.
Total Posts : 97
Contribute Your Articles

Subscribe Us

Like Us On Facebook