48

I know in Java we can create an instance of a Class by new, clone(), Reflection and by serializing and de-serializing.

I have create a simple class implementing a Singleton.

And I need stop all the way one can create instance of my Class.

public class Singleton implements Serializable{
    private static final long serialVersionUID = 3119105548371608200L;
    private static final Singleton singleton = new Singleton();
    private Singleton() { }
    public static Singleton getInstance(){
        return singleton;
    }
    @Override
    protected Object clone() throws CloneNotSupportedException {
        throw new CloneNotSupportedException("Cloning of this class is not allowed"); 
    }
    protected Object readResolve() {
        return singleton;
    }
    //-----> This is my implementation to stop it but Its not working. :(
    public Object newInstance() throws InstantiationException {
        throw new InstantiationError( "Creating of this object is not allowed." );
    }
}

In this Class I have managed to stop the class instance by new, clone() and serialization, But am unable to stop it by Reflection.

My Code for creating the object is

try {
    Class<Singleton> singletonClass = (Class<Singleton>) Class.forName("test.singleton.Singleton");
    Singleton singletonReflection = singletonClass.newInstance();
} catch (ClassNotFoundException e) {
    e.printStackTrace();
} catch (InstantiationException e) {
    e.printStackTrace();
} catch (IllegalAccessException e) {
    e.printStackTrace();
}
3
  • 1
    You have accepted the wrong answer - the right one is stackoverflow.com/a/6994437/281545 Commented Sep 28, 2013 at 18:15
  • All answers are not solving this problem. Commented Apr 7, 2017 at 8:39
  • I know that my question is somehow out of scope but can you tell me how did you managed to stop creating a class instance via reflexion ? I couldn't see such a thing in your code Commented Jan 12, 2019 at 0:58

12 Answers 12

75

By adding below check inside your private constructor

private Singleton() {
    if( singleton != null ) {
        throw new InstantiationError( "Creating of this object is not allowed." );
    }
}
Sign up to request clarification or add additional context in comments.

8 Comments

There is a flaw in this approach, by which what if we create the instance using reflection before any getInstance invocation(with lazy init)? Reflection is still allowed to proceed as the static variable is still null at that time.
I agree with @ringbearer , you can create as many objects using reflection as you like for this class, if the getIntance method is not invoked.
@ringbearer When you try to create an instance of a class, whether via Reflection or directly, the class will be initialized, including the execution of field initializers. It doesn’t matter whether the getInstance has been invoked or not. Since the field initializer comes first, this approach will reject any Reflection instantiation attempts.
@HrishikeshMishra you obviously never tried what you have posted.
Not exactly when the class is loaded (as the time of loading is not exactly specified), but definitely before an instance is created as specified. That’s sufficient for your approach. It’s annoying to see three comments wrongly claiming that this didn’t work.
|
23

Define the singleton like this:

public enum Singleton {
    INSTANCE
}

6 Comments

Enum is a sure shot gaurantee against Reflection,clone and serialization-deserialization
But ENUM has it's restriction. I am actually looking for a solution which is apart from ENUM
@Diganta what restrictions?
Enum is the cleanest way of providing singleton behavior in Java, bar none. As Kumar Abhinav stated, it provides these guarantees in the simplest, least error prone way.
@ihebiheb that’s not a restriction at all. When you deserialize an object its class is not a singleton anymore. An enum type with exactly one constant is the only thing you can serialize and deserialize without breaking the singleton invariant, as indeed, it doesn’t store nor restore state but resolves to the already existing singleton.
|
16

How about checking in the constructor:

private Singleton() {
    if (singleton != null) {
        throw new IllegalStateException("Singleton already constructed");
    }
}

Of course, this may not really stop it - if someone is messing around with reflection to access private members, they may be able to set the field to null themselves. You have to ask yourself just what you're trying to prevent though, and how worthwhile it is.

(EDIT: As Bozho mentioned, final fields may not be settable even via reflection. I wouldn't be surprised if there were some way of doing it via JNI etc though... if you give folks enough access, they'll be able to do almost anything...)

4 Comments

I think final fields can't be modified with reflection
hey - the right way is the enum one - see : stackoverflow.com/a/71399/281545. Actually item 77 of effective java 2nd edition demonstrates a (too technical for me) attack via deserialization that would probably beat this constructor (?)
This approach will not work if we create object first reflection, like this String className = "Singleton"; Class<Singleton> aClass = (Class<Singleton>) Class.forName(className); Constructor<?> declaredConstructor = aClass.getDeclaredConstructor(); declaredConstructor.setAccessible(true); Singleton instance1 = (Singleton) declaredConstructor.newInstance(); print("instance1", instance1.hashCode()); Singleton instance2 = Singleton.getInstance(); print("instance2", instance2.hashCode()); both have different hashcode
10
private Singleton() { 
    if (Singleton.singleton != null) {
        throw new RuntimeException("Can't instantiate singleton twice");
    }
}

Another thing you should watch is the readResolve(..) method, because your class implements Serialiable. There you should return the existing instance.

But the easiest way to use singletons is through enums - you don't worry about these things.

5 Comments

Luckily I have already implemented the readResolve() method.
This approach will not work if we create object first reflection, like this String className = "Singleton"; Class<Singleton> aClass = (Class<Singleton>) Class.forName(className); Constructor<?> declaredConstructor = aClass.getDeclaredConstructor(); declaredConstructor.setAccessible(true); Singleton instance1 = (Singleton) declaredConstructor.newInstance(); print("instance1", instance1.hashCode()); Singleton instance2 = Singleton.getInstance(); print("instance2", instance2.hashCode()); both have different hashcode
@HrishikeshMishra: Nope, when you call the constructor via reflection it throws an exception. I've just tried your code, and it threw an exception as expected...
@JonSkeet, it will work of egger initialization but will not lazy. try out.
@HrishikeshMishra: Don't know what you mean by that, but I tried the exact code you showed. Note that the class will be initialized before you get to call the constructor, in any reasonable VM...
1

As an alternative to the singleton, you could take a look at the monostate pattern. Then, instantiation of your class is not a problem anymore, and you don't have to worry about any of the scenarios you listed.

In the monostate pattern, all the fields in your class are static. That means that all instances of the class share the same state, just like with a singleton. Moreover, this fact is transparent to the callers; they don't need to know about special methods like getInstance, they simply create instances and work with them.

But, just like with singleton, it's a form of hidden global state; which is very bad.

Comments

1

Apart the enum solution, all the others can be workaround-ed via Reflexion These are two examples on how to workaround the Dave G Solution :

1 : Setting the variable Singleton.singleton to null

Constructor<?>[] constructors = Singleton.class.getDeclaredConstructors();
Constructor theConstructor = constructors[0];
theConstructor.setAccessible(true);
Singleton instance1 = (Singleton) theConstructor.newInstance();

Singleton.getInstance();

Field f1 = Singleton.class.getDeclaredField("singleton");
f1.setAccessible(true);
f1.set(f1, null);
Singleton instance2 = (Singleton) theConstructor.newInstance();

System.out.println(instance1);
System.out.println(instance2);

Output :

  • Singleton@17f6480
  • Singleton@2d6e8792

2 : not calling the getInstance

Constructor<?>[] constructors = Singleton.class.getDeclaredConstructors();
Constructor theConstructor = constructors[0];
theConstructor.setAccessible(true);
Singleton instance1 = (Singleton) theConstructor.newInstance();
Singleton instance2 = (Singleton) theConstructor.newInstance();

System.out.println(instance1);
System.out.println(instance2);

Output :

  • Singleton@17f6480
  • Singleton@2d6e8792

So I can think of 2 ways if you don't want to go with an Enum :

1st option : Using the securityManager :

It prevent from using unauthorized operations (calling private methods from outside the class ....)

So you just need to add one line to the singleton constructor proposed by the other answers

private Singleton() {
    if (singleton != null) {
        throw new IllegalStateException("Singleton already constructed");
    }
    System.setSecurityManager(new SecurityManager());
}

what it does is that it prevents from calling setAccessible(true) So when you want to call it :

Constructor<?>[] constructors = Singleton.class.getDeclaredConstructors();
Constructor theConstructor = constructors[0];
theConstructor.setAccessible(true);

this exeption will occure : java.security.AccessControlException: access denied ("java.lang.RuntimePermission" "createSecurityManager")

2nd option : In the singleton constructor, test if the call is made via Reflexion :

I refer you to this other Stackoverflow thread for the best way to get the caller class or method.

So If I add this in the Singleton constructor :

String callerClassName = new Exception().getStackTrace()[1].getClassName();
System.out.println(callerClassName);

And I call it like this :

Constructor<?>[] constructors = Singleton.class.getDeclaredConstructors();
Constructor theConstructor = constructors[0];
theConstructor.setAccessible(true);
Singleton instance1 = (Singleton) theConstructor.newInstance();

the output will be : jdk.internal.reflect.DelegatingConstructorAccessorImpl

but if I call it regularly (Instantiating a public constructor or calling a method without Reflexion) the name of the class of the calling method is printed. So for example I have :

public class MainReflexion {
    public static void main(String[] args) {
        Singleton.getInstance();
    }
}

the callerClassName will be MainReflexion and so the output will be MainReflexion.


PS : If workarounds exists for the proposed solutions please let me know

5 Comments

If you set Security manager than you are not able to call SingletonClass sc = SingletonClass.getInstance(); you will get exception every time.
Neither of your workarounds works with class given in the question. Instantiation via Reflection still executes the class initializer first, further, you can’t change a static final field via Reflection.
@Holger You can chang a static final field via reflection without SecurityManager. see https://stackoverflow.com/a/3301720/7772947
@xmcx first of all that doesn’t change the fact that the code examples given in this answer do not do what the answer claims. Further, what you have linked is an unsupported hack that stops working with Java 12.
@Holger Yes, I noticed, thanks for reminding me.
0

Just to note, that as of Java 8 and according to my check- you cannot instantiate a Singleton via Reflections as long as it has a private constructor.

You'll get this exception:

Exception in thread "main" java.lang.IllegalAccessException: Class com.s.Main can not access a member of class com.s.SingletonInstance with modifiers "private"
at sun.reflect.Reflection.ensureMemberAccess(Unknown Source)
at java.lang.Class.newInstance(Unknown Source)
at com.s.Main.main(Main.java:6)

1 Comment

Yes you can Constructor<?>[] constructors = Counter.class.getDeclaredConstructors(); Constructor theConstructor = constructors[0]; //suppose you have 1 constructor theConstructor.setAccessible(true); theConstructor.newInstance();
0

I Thing Below code will work ..

class Test {

    static private Test t = null;
    static {
        t = new Test();
    }

    private Test(){}

    public static Test getT() {
        return t;
    }

    public String helloMethod() {
        return "Singleton Design Pattern";
    }
}


public class MethodMain {

    public static void main(String[] args) {
        Test t = Test.getT();
        System.out.println(t.helloMethod());
    }
}

output : Singleton Design Pattern

Comments

0

We can break it using static nested class

Please follow below code its 100% correct, i tested

package com.singleton.breakable;

import java.io.Serializable;

class SingletonImpl implements Cloneable, Serializable {

    public static SingletonImpl singleInstance = null;

    private SingletonImpl() {

    }

    @Override
    protected Object clone() throws CloneNotSupportedException {
        return singleInstance;
    };

    public Object readResolve() {
        return SingletonImpl.getInstance(); // 
    }

    public static SingletonImpl getInstance() {

        if (null == singleInstance) {
            singleInstance = new SingletonImpl();
        }
        return singleInstance;
    }

}


package com.singleton.breakable;

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.lang.reflect.Constructor;

class FullySingletonClass {

    public static void main(String[] args) {

        SingletonImpl object1 = SingletonImpl.getInstance();
        System.out.println("Object1:" + object1);

        try {
            FileOutputStream fos = new FileOutputStream("abc.txt");
            ObjectOutputStream oos = new ObjectOutputStream(fos);
            oos.writeObject(object1);

            FileInputStream fis = new FileInputStream("abc.txt");
            ObjectInputStream ois = new ObjectInputStream(fis);
            SingletonImpl object2 = (SingletonImpl) ois.readObject();
            System.out.println("Object2" + object2);

        } catch (Exception e) {
            // TODO: handle exception
        }
        try {
            Constructor[] constructors = SingletonImpl.class.getDeclaredConstructors();
            for (Constructor constructor : constructors) {
                // Below code will not destroy the singleton pattern
                constructor.setAccessible(true);
                SingletonImpl Object3 = (SingletonImpl) constructor.newInstance();
                System.out.println("Object3: Break through Reflection:" + Object3);
                break;
            }
        } catch (Exception ew) {

        }

    }
}

**OUTPUT**
Object1:com.singleton.breakable.SingletonImpl@15db9742
Object2com.singleton.breakable.SingletonImpl@15db9742
Object3: Break through Reflection:com.singleton.breakable.SingletonImpl@33909752

2 Comments

Here its breaking with Reflection API by making constructor as visible, So please follow the below code provided by me , (Ashish Agrawal), Code is fully singleton
The question was how to prevent this, not to demonstrate that it’s possible. The text of your answer, the code example, and your comment are all contradicting each other.
0

Perfect Singleton Class that can avoid instance creation during serialization, clone and reflection.

import java.io.Serializable;

public class Singleton implements Cloneable, Serializable {

    private static final long serialVersionUID = 1L;
    private static volatile Singleton instance;

    private Singleton() {
        if (instance != null) {
            throw new InstantiationError("Error creating class");
        }
    }

    public static Singleton getInstance() {
        if (instance == null) {
            synchronized (Singleton.class) {

                if (instance == null) {
                    return new Singleton();
                }
            }
        }
        return null;
    }

    @Override
    protected Object clone() throws CloneNotSupportedException {
        throw new CloneNotSupportedException();
    }

    Object readResolve() {
        return Singleton.getInstance();
    }

}

Comments

0

Approach with Lazy initialization:

  private static Singleton singleton;

  public static Singleton getInstance() {
    if(singleton==null){
      singleton= new Singleton();
    }
    return singleton;
  }


private Singleton() {
    if (Singleton.singleton != null) {
      throw new InstantiationError("Can't instantiate singleton twice");
    }
    Singleton.singleton = this;
}

This approach works even if you decide to create an instance using reflection before any getInstance invocation

Comments

-3
Here Reflection not work     

    package com.singleton.nonbreakable;

        import java.io.FileInputStream;
        import java.io.FileOutputStream;
        import java.io.ObjectInputStream;
        import java.io.ObjectOutputStream;
        import java.lang.reflect.Constructor;

        class FullySingletonClass {

            public static void main(String[] args) {

                SingletonImpl object1 = SingletonImpl.getInstance();
                System.out.println("Object1:" + object1);

                try {
                    FileOutputStream fos = new FileOutputStream("abc.txt");
                    ObjectOutputStream oos = new ObjectOutputStream(fos);
                    oos.writeObject(object1);

                    FileInputStream fis = new FileInputStream("abc.txt");
                    ObjectInputStream ois = new ObjectInputStream(fis);
                    SingletonImpl object2 = (SingletonImpl) ois.readObject();
                    System.out.println("Object2" + object2);

                } catch (Exception e) {
                    // TODO: handle exception
                }
                try {
                    Constructor[] constructors = SingletonImpl.class.getDeclaredConstructors();
                    for (Constructor constructor : constructors) {
                        // Below code will not destroy the singleton pattern
                        constructor.setAccessible(true);
                        SingletonImpl Object3 = (SingletonImpl) constructor.newInstance();
                        System.out.println("Object3:" + Object3);
                        break;
                    }
                } catch (Exception ew) {

                }

            }
        }


    package com.singleton.nonbreakable;

    import java.io.Serializable;

    class SingletonImpl implements Cloneable, Serializable {

        public static SingletonImpl singleInstance = null;

        private static class SingletonHolder {
            public static SingletonImpl getInstance() {
                if (null == singleInstance) {
                    singleInstance = new SingletonImpl();
                }
                return singleInstance;
            }
        }

        private SingletonImpl() {

        }

        @Override
        protected Object clone() throws CloneNotSupportedException {
            return singleInstance;
        };

        public Object readResolve() {
            System.out.println("Executing readResolve again");
            return SingletonImpl.getInstance(); // FIXME
        }

        public static SingletonImpl getInstance() {

            return SingletonHolder.getInstance();
        }

    }

    Output : 
    Object1:com.singleton.nonbreakable.SingletonImpl@15db9742
    Executing readResolve again
    Object2com.singleton.nonbreakable.SingletonImpl@15db9742

2 Comments

this is pure Singleton, This code will not break in any case like- Cloning,Serialization, Reflection.
This is Cargo Cult programming. You’re using patterns without understanding their purpose. For example, your nested SingletonHolder class makes no sense at all, as it is not actually a holder class. Compared to what the questioner already provided, you only made things worse, by removing thread safety, for example, without providing any additional protection. Your code breaks, because you’re looping over all constructors and try to invoke each without arguments. Just use Constructor constructor = SingletonImpl.class.getDeclaredConstructor(); to get the right no-arg constructor instead.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.