Singleton cracking in other ways

I did research on singleton, and I developed a very simple singleton class.

public class SingletonObject { private static SingletonObject ref; private SingletonObject () //private constructor { } public static synchronized SingletonObject getSingletonObject() { if (ref == null) ref = new SingletonObject(); return ref; } public Object clone() throws CloneNotSupportedException {throw new CloneNotSupportedException (); } } 

Now below is one way I broke singleton.

 public class CrackingSingleton { public static void main(String[] args) throws ClassNotFoundException, IllegalArgumentException, SecurityException, InstantiationException, IllegalAccessException, InvocationTargetException { //First statement retrieves the Constructor object for private constructor of SimpleSingleton class. Constructor pvtConstructor = Class.forName("CrackingSingleton.SingletonObject").getDeclaredConstructors()[0]; //Since the constructor retrieved is a private one, we need to set its accessibility to true. pvtConstructor.setAccessible(true); //Last statement invokes the private constructor and create a new instance of SimpleSingleton class. SingletonObject notSingleton1 = ( SingletonObject) pvtConstructor.newInstance(null); System.out.println(notSingleton1.hashCode()); System.out.println("notSingleton1 --->"+notSingleton1.toString()); SingletonObject notSingleton2 = ( SingletonObject) pvtConstructor.newInstance(null); System.out.println("notSingleton2 --->"+notSingleton2.hashCode()); System.out.println(notSingleton2.toString()); } } 

Please inform in another way that a singleton can be hacked. !!

+1
source share
6 answers

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; //ensure singleton is returned upon deserialization. } } 

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()); 
+5
source

If you have two class loaders, you can create a singleton from each class loader.

The document "When it's a Singleton, Not a Single" is also worth reading.

+2
source

I answer:

Why does it matter?

If you are trying to create safe, non-verifiable code, then Singleton is not the solution. It is designed to force a regular developer to use your instance of your system. All these workarounds require a lot of extra work that someone is not going to do just to use another instance of the class.

+1
source

Through reflection, set ref = null . By re-assigning it to null , the lazy singleton logic will be run again the next time getSingletonObject called.

0
source

You can make the singleton constructor publicly available using byte code development libraries.

In addition, in some older versions of Java (this is used to work in 1.3), you can simply create a class with the same name, with an open constructor and compilation against this class. At run time, this allowed you to instantiate a real class (this loophole has been fixed in bytecode verification in later versions of the JRE).

0
source

There are several scenarios in which Singleton does not behave.

1. If Singleton Classes are destroyed by garbage collection, reboot again.
2. More than one singleton in more than one virtual machine
3. More than one singleton, simultaneously loaded with all kinds of loaders.
4Copies of a Singleton object that has been serialized and deserialized

0
source

All Articles