Singleton design pattern is intended to create only one instance of given class in context of given class loader (class loader which loads this given class). i.e: One instance per class loader. This post will discuss how to exploit a Singleton class with Reflection API and create multiple instance of that class followed by how do we resolve it.
Below is a singleton class with instance created while class is loaded in JVM by a class loader.
In order to prevent multiple object creation, above class provides private constructor and it looks logical. But Java provides reflection API with we can create Multiple instance of this class and it breaks Singleton goal of creating only one instance of given class.
Lets use reflection API and try to create multiple object. Below sample class makes private constructor accessible using Reflection API and create another object from outside (other than provided by Singleton class SingletonBreakable)
Sample Output:-
Hashcode of original object is 576315909
Hello from SingletonBreakable
Hashcode of Duplicate Object is 990234593
Hello from SingletonBreakable
Hashcode of both object is different, it indicates we are able to create multiple object using reflection. It breaks Singleton contract and claim to create Just one instance of this class with respect of one class loader.
We have added a check in above constructor, if we will try to create instance of this class, exception will be thrown and object creation will not be successful. Now we try to create duplicate object and validate the modification.
Sample Output:-
Hashcode of original object is 1486987673
Hello from SingletonThrowException
java.lang.reflect.InvocationTargetException
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:57)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.lang.reflect.Constructor.newInstance(Constructor.java:526)
at javacore.SingletonUnbreakableClinet.createObjetUsingRefletion(SingletonUnbreakableClinet.java:32)
at javacore.SingletonUnbreakableClinet.main(SingletonUnbreakableClinet.java:18)
Caused by: java.lang.IllegalStateException: Already instantiated
at javacore.SingletonThrowException.<init>(SingletonThrow.java:56)
... 6 more
Object creation failed !!
Below is a singleton class with instance created while class is loaded in JVM by a class loader.
class SingletonBreakable { private static final SingletonBreakable INSTANCE = new SingletonBreakable(); private SingletonBreakable() { // No object creation allowed from outside world } public static SingletonBreakable getInstance() { return INSTANCE; } public Object clone() throws CloneNotSupportedException { throw new CloneNotSupportedException( "Cannot clone instance of this class"); } public void display() { System.out.println("Hello from SingletonBreakable"); } }
In order to prevent multiple object creation, above class provides private constructor and it looks logical. But Java provides reflection API with we can create Multiple instance of this class and it breaks Singleton goal of creating only one instance of given class.
Lets use reflection API and try to create multiple object. Below sample class makes private constructor accessible using Reflection API and create another object from outside (other than provided by Singleton class SingletonBreakable)
package javacore; import java.lang.reflect.Constructor; public class SingletonBreakableClinet { /** * @param args */ public static void main(String[] args) { /* * 1.Execute display method using default object provided by * SingletonBreakable and display hashCode too. */ SingletonBreakable sb1 = SingletonBreakable.getInstance(); System.out.println("Hashcode of original object is " + sb1.hashCode()); sb1.display(); /* * 2. Use reflection to create duplicateObject and display its hashCode. */ SingletonBreakable sb2 = createObjetUsingRefletion(); System.out.println("Hashcode of Duplicate Object is " + sb2.hashCode()); sb2.display(); } public static SingletonBreakable createObjetUsingRefletion() { SingletonBreakable sb = null; try { Constructor<SingletonBreakable> constructor = SingletonBreakable.class .getDeclaredConstructor(new Class[0]); constructor.setAccessible(true); sb = constructor.newInstance(); } catch (Exception e) { e.printStackTrace(); } return sb; } }
Sample Output:-
Hashcode of original object is 576315909
Hello from SingletonBreakable
Hashcode of Duplicate Object is 990234593
Hello from SingletonBreakable
Hashcode of both object is different, it indicates we are able to create multiple object using reflection. It breaks Singleton contract and claim to create Just one instance of this class with respect of one class loader.
How to prevent reflection to create multiple instance of Singleton ?
Instead of creating a empty private constructor, we need to throw exception from it, if instance is already created (which will be always created as class is loaded). So modified class is:class SingletonThrowException { private static final SingletonThrowException INSTANCE = new SingletonThrowException(); private SingletonThrowException() { if (INSTANCE != null) { throw new IllegalStateException("Already instantiated"); } } public static SingletonThrowException getInstance() { return INSTANCE; } public Object clone() throws CloneNotSupportedException { throw new CloneNotSupportedException( "Cannot clone instance of this class"); } public void display() { System.out.println("Hello from SingletonThrowException "); } }
We have added a check in above constructor, if we will try to create instance of this class, exception will be thrown and object creation will not be successful. Now we try to create duplicate object and validate the modification.
package javacore; import java.lang.reflect.Constructor; public class SingletonUnbreakableClinet { public static void main(String[] args) { /* * 1.Execute display method using default object provided by * SingletonBreakable and display hashCode too. */ SingletonThrowException sb1 = SingletonThrowException.getInstance(); System.out.println("Hashcode of original object is " + sb1.hashCode()); sb1.display(); /* * 2. Use reflection to create duplicateObject and display its hashCode. */ SingletonThrowException sb2 = createObjetUsingRefletion(); if (sb2 != null) System.out.println("Hashcode of Duplicate Object is " + sb2.hashCode()); else System.out.println("Object creation failed !!"); } public static SingletonThrowException createObjetUsingRefletion() { SingletonThrowException sb = null; try { Constructor<SingletonThrowException> constructor = SingletonThrowException.class .getDeclaredConstructor(new Class[0]); constructor.setAccessible(true); sb = constructor.newInstance(); } catch (Exception e) { e.printStackTrace(); } return sb; } }
Sample Output:-
Hashcode of original object is 1486987673
Hello from SingletonThrowException
java.lang.reflect.InvocationTargetException
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:57)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.lang.reflect.Constructor.newInstance(Constructor.java:526)
at javacore.SingletonUnbreakableClinet.createObjetUsingRefletion(SingletonUnbreakableClinet.java:32)
at javacore.SingletonUnbreakableClinet.main(SingletonUnbreakableClinet.java:18)
Caused by: java.lang.IllegalStateException: Already instantiated
at javacore.SingletonThrowException.<init>(SingletonThrow.java:56)
... 6 more
Object creation failed !!
Here only one instance of object is created and when reflection API tries to create an instance it fails. so in this way we can prevent Object creation using reflection API.
Summary :- "Always throws Exception from private constructor in the case of Singleton class."
Aivivu chuyên vé máy bay, tham khảo
ReplyDeleteve may bay di my gia re
ve may bay tu my ve vietnam
chuyến bay từ frankfurt đến hà nội
lịch bay từ hà nội đến nga
giá vé máy bay từ anh về việt nam
các chuyến bay từ châu âu về việt nam
bảng giá khách sạn cách ly tphcm
ve may bay chuyen gia nuoc ngoai sang Viet Nam
This post was enjoyable to me. It provided insightful information, and I'm eager to put some of your suggestions into practice. I appreciate your sharing.
ReplyDeletejava with DSA course