I have a singleton like this.
public class BookingFactory { private final static BookingFactory instance; static { instance = new BookingFactory(); } public static BookingFactory getInstance() { return instance; } private BookingFactory() { System.out.println("Object is created."); } } public class Test { BookingFactory instance = BookingFactory.getInstance(); instance = BookingFactory.getInstance(); Class<?> clazz = Class.forName("com.test.BookingFactory"); Constructor pvtConstructor = clazz.getDeclaredConstructors()[0]; // Set its access control pvtConstructor.setAccessible(true); // Invoke Private Constructor BookingFactory notSingleton = (BookingFactory) pvtConstructor.newInstance(null); }
When I run this, I saw more than one printout message. Is there any way to prevent this singleton from being instantiated more than once from this reflection?
Thanks.
There are many ways to prevent Singleton pattern from Reflection API, but one of the best solutions is to throw a run-time exception in the constructor if the instance already exists. In this, we can not able to create a second instance.
Overcome Cloning issue:- To overcome this issue, override clone() method and throw an exception from clone method that is CloneNotSupportedException. Now whenever user will try to create clone of singleton object, it will throw exception and hence our class remains singleton.
Answer: You can prevent this by using readResolve() method, since during serialization readObject() is used to create instance and it return new instance every time but by using readResolve you can replace it with original Singleton instance.
1. Reflection: In Java, Reflection API is used to explore or change the behavior of methods, interfaces, classes at runtime. As you can see that 2 different hashcodes are created for singleton class. Hence singleton pattern has been destroyed using Reflection.
Try using an enum
. enums make for good Singletons.
public static enum BookingFactory { INSTANCE; public static BookingFactory getInstance() { return INSTANCE; } }
You can't create an enum via reflection.
The getInstance() method is superfluous but makes it easier to run your test, throwing the following exception:
java.lang.IllegalArgumentException: Cannot reflectively create enum objects at java.lang.reflect.Constructor.newInstance(Constructor.java:530) at MultiSingletonTest.main(MultiSingletonTest.java:40)
Oh look, someone already gave the enum answer. Posting anyway for more completeness.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With