I was doing research on singleton and I have developed a very basic singleton class..
public class SingletonObject {
private static SingletonObject ref;
Three ways I can think of are:
If your singleton class is serializable, then you could serialize an instance of it, and deserialize it back and get a second object of that class.
You could avoid this by implementing 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; //ensure singleton is returned upon deserialization.
}
}
The same class could be loaded by two different class loaders, as such, you could create two instances of your singleton class by simply invoking its getInstance method in a class loaded by two different class loaders. This approach would work without having to resort to violating the 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);
As you have well pointed out, via reflection you could create two instances of the class. I think the previous examples was just a variant of the same approach. But I believe you could prevent these two from happening using a SecurityManager.
System.setSecurityManager(new SecurityManager());