2

I was doing research on singleton and I have developed a very basic 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 the one way which I have cracked the 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 advise other ways also by which the singleton can be cracked..!!

user1538526
  • 95
  • 7
  • 22

6 Answers6

5

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());
Edwin Dalorzo
  • 76,803
  • 25
  • 144
  • 205
  • Its noteworthy that the The class loading approach does not really *break* the Singleton, since the same class loaded twice trough different classloaders (from the VMs point of view) are not the same class. They are also not assignment compatible. – Durandal Jul 25 '12 at 17:11
  • @Edwin perfect could you please post the updated code through serialization and class loading..that will be a great help as I have done through reflection..Thanks MAN – user1538526 Jul 25 '12 at 17:14
  • Well, it depends on the definition of a Singleton then. Do we consider it a Singleton if we can have more then one instance in a single JVM process? Even when the two separately loaded classes are not assignment-compatible as you suggest, from a functional standpoint, I do have two instances of a class of which I was supposed to have only 1. That's all I wanted to demonstrate. – Edwin Dalorzo Jul 25 '12 at 17:19
2

If you have two classloaders, you'll be able to create a singleton from each classloader.

The document "When is a singleton not a singleton" is also worth a read.

Brian Agnew
  • 268,207
  • 37
  • 334
  • 440
1

My answer is:

Why does it matter?

If you are trying to design secure, uncrackable code then a Singleton is not a solution for that. It is designed to force the ordinary developer to use your system instance of it. All of these methods of getting around it require a lot of extra work that someone is not going to do simply to use a different instance of the class.

Matt N
  • 146
  • 5
0

Via reflection, set ref = null. By re-assigning it as null, the logic to lazily construct the singleton will be triggered again on the next invocation of getSingletonObject.

Tim Bender
  • 20,112
  • 2
  • 49
  • 58
0

You can make the singleton constructor public using byte code engineering libraries.

Also, in some older Java versions (this used to work in 1.3), you can simply create a class with the same name, with public constructor and the compile against that class. At runtime this allowed you to create instances of the real class (this loophole has been fixed in the bytecode verification in later JRE versions).

Durandal
  • 19,919
  • 4
  • 36
  • 70
0

There are some scenarios where Singleton doesn't behave like.

1.If Singleton Classes destroyed by Garbage Collection, then Reloaded again.
2.More than one Singletons in more than one Virtual Machines
3.More than one Singletons Simultaneously Loaded by Different Class Loaders.
4Copies of Singleton Object that has Undergone Serialization and Deserialization

Singh123
  • 216
  • 3
  • 10