cracking singleton with other ways

后端 未结 6 730
情深已故
情深已故 2020-12-07 05:20

I was doing research on singleton and I have developed a very basic singleton class..

public class SingletonObject {
    private static SingletonObject ref;
         


        
6条回答
  •  南笙
    南笙 (楼主)
    2020-12-07 06:05

    Three ways I can think of are:

    Serialization

    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.
       }
    }
    

    Class Loading

    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);
    

    Reflection

    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());
    

提交回复
热议问题