The three ways I can think of are as follows:
Serialization
If your singleton class is serializable, you can serialize its instance and deserialize it and get the second object of this class.
You can avoid this by running the readResolve method .
public class Singleton implements Serializable { private static final Singleton INSTANCE = new Singleton(); public static Singleton getInstance(){ return INSTANCE; } public Object readResolve() throws ObjectStreamException { return INSTANCE;
Class loading
The same class can be loaded by two different class loaders, so you can create two instances of your singleton class by simply calling its getInstance method on the class loaded by two different class loaders. This approach will work without having to resort to violating a private constructor.
ClassLoader cl1 = new URLClassLoader(new URL[]{"singleton.jar"}, null); ClassLoader cl2 = new URLClassLoader(new URL[]{"singleton.jar"}, null); Class<?> singClass1 = cl1.loadClass("hacking.Singleton"); Class<?> singClass2 = cl2.loadClass("hacking.Singleton"); //... Method getInstance1 = singClass1.getDeclaredMethod("getInstance", ...); Method getInstance2 = singClass2.getDeclaredMethod("getInstance", ...); //... Object singleton1 = getInstance1.invoke(null); Object singleton2 = getInstance2.invoke(null);
Reflection
As you well pointed out, through reflection, you can create two instances of the class. I think the previous examples were just a variant of the same approach. But I believe that you could prevent these two events using the SecurityManager .
System.setSecurityManager(new SecurityManager());
source share