1

I was going through singleton pattern, below is my singleton class..

    package CrackingSingleton;

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

and I was going through the way to break it, below is my piece of code...

 package CrackingSingleton;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;

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.java").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);
         SingletonObject  notSingleton2 = ( SingletonObject) pvtConstructor.newInstance(null);
    }
}

But upon executing the above class CrackingSingleton it throws the error...

Exception in thread "main" java.lang.ClassNotFoundException: CrackingSingleton.SingletonObject.java
at java.net.URLClassLoader$1.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(Unknown Source)
at java.lang.ClassLoader.loadClass(Unknown Source)
at sun.misc.Launcher$AppClassLoader.loadClass(Unknown Source)
at java.lang.ClassLoader.loadClass(Unknown Source)
at java.lang.Class.forName0(Native Method)
at java.lang.Class.forName(Unknown Source)
at CrackingSingleton.CrackingSingleton.main(CrackingSingleton.java:14)
skaffman
  • 398,947
  • 96
  • 818
  • 769
dghtr
  • 561
  • 3
  • 6
  • 20

3 Answers3

3

You're adding .java to your classname. Java classnames do not include .java. So your code should read

Constructor pvtConstructor = Class.forName("crackingsingleton.SingletonObject").getDeclaredConstructors()[0];

Note that I changed your package name to not be capitalized.

Tim Pote
  • 27,191
  • 6
  • 63
  • 65
1

This happens because you are asking for a wrong class. Which is by the way clearly stated in the stacktrace also.

// This should work
// There is no need to add .java or .class declaration. 
Class.forName("CrackingSingleton.SingletonObject")

That being said, then you might want to consider using ENUM singleton pattern.

Community
  • 1
  • 1
Kirstein
  • 893
  • 8
  • 10
1

I suggest trying this instead. enum is much simpler and more robust.

package crackingSingleton;

public enum SingletonObject {
    INSTANCE;
}

package crackingSingleton;

import java.lang.reflect.Constructor;

public class CrackingSingleton {
    public static void main(String... args) throws Exception {
        //First statement retrieves the Constructor object for private constructor of SimpleSingleton class.
        Constructor pvtConstructor = crackingSingleton.SingletonObject.class.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);
        SingletonObject  notSingleton2 = ( SingletonObject) pvtConstructor.newInstance(null);
    }
}

prints

Exception in thread "main" java.lang.IllegalArgumentException: Cannot reflectively create enum objects
    at java.lang.reflect.Constructor.newInstance(Constructor.java:520)
    at crackingSingleton.CrackingSingleton.main(CrackingSingleton.java:12)
Peter Lawrey
  • 525,659
  • 79
  • 751
  • 1,130
  • Can you please expalin the enum in detail..? – dghtr Apr 24 '12 at 16:42
  • 1
    The `enum Singleton` is a class with one and only one instance called `INSTANCE` It is lazy loaded and its construction is thread safe. You don't need to use a lock to get the instance making it faster and more efficient. It has a private constructor and cannot be created using reflection. It can have instance methods and can implement interfaces. IMHO, It is much simplier and clearer than the alternatives. What else would you like to know? – Peter Lawrey Apr 24 '12 at 17:38