46

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();
}
Talha Ahmed Khan
  • 15,043
  • 10
  • 42
  • 49

12 Answers12

72

By adding below check inside your private constructor

private Singleton() {
    if( singleton != null ) {
        throw new InstantiationError( "Creating of this object is not allowed." );
    }
}
Ahmed Nabil
  • 17,392
  • 11
  • 61
  • 88
Dave G
  • 9,639
  • 36
  • 41
  • I just used what was technically the body of newInstance(). I think, although not sure, the newInstance() method can be removed as that is actually a java.lang.Class> method and the method implementation provided in the question initially would do nothing. – Dave G Aug 09 '11 at 10:14
  • 9
    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. – ring bearer Jun 16 '15 at 19:22
  • 1
    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. – Kanwaljeet Singh Jan 23 '16 at 05:32
  • This approach will not work if we create object first reflection, like this String className = "Singleton"; Class aClass = (Class) 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 – Hrishikesh Mishra Apr 07 '17 at 08:35
  • 2
    @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. – Holger Apr 12 '22 at 09:59
  • 1
    @HrishikeshMishra you obviously never tried what you have posted. – Holger Apr 12 '22 at 09:59
  • I posted this answer 11 years ago. As per this documentation https://docs.oracle.com/javase/tutorial/java/javaOO/initial.html the static initialization block will run the moment the class is loaded. – Dave G Apr 12 '22 at 19:02
  • 2
    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](https://docs.oracle.com/javase/specs/jls/se17/html/jls-12.html#jls-12.4.1). That’s sufficient for your approach. It’s annoying to see three comments wrongly claiming that this didn’t work. – Holger Apr 13 '22 at 10:30
23

Define the singleton like this:

public enum Singleton {
    INSTANCE
}
Arne Deutsch
  • 14,629
  • 5
  • 53
  • 72
  • 1
    Enum is a sure shot gaurantee against Reflection,clone and serialization-deserialization – Kumar Abhinav Aug 13 '14 at 10:50
  • But ENUM has it's restriction. I am actually looking for a solution which is apart from ENUM – Diganta Jun 27 '17 at 09:01
  • 1
    @Diganta what restrictions? – GorvGoyl Sep 02 '17 at 13:10
  • 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. – Tom Drake Jan 21 '18 at 02:04
  • One restriction I can think of is when serializing an enum, field variables are not getting serialized (will lose the value of the field) – ihebiheb Jan 19 '19 at 03:36
  • 1
    @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. – Holger Jun 16 '23 at 07:10
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...)

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • I think final fields can't be modified with reflection – Bozho Aug 09 '11 at 10:06
  • related: http://www.javaspecialists.eu/archive/Issue161.html, http://www.javaspecialists.eu/archive/Issue096.html – Bozho Aug 09 '11 at 11:48
  • hey - the right way is the enum one - see : http://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 (?) – Mr_and_Mrs_D Sep 28 '13 at 18:14
  • This approach will not work if we create object first reflection, like this String className = "Singleton"; Class aClass = (Class) 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 – Hrishikesh Mishra Apr 07 '17 at 08:37
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.

Bozho
  • 588,226
  • 146
  • 1,060
  • 1,140
  • Luckily I have already implemented the `readResolve()` method. – Talha Ahmed Khan Aug 09 '11 at 10:07
  • 1
    This approach will not work if we create object first reflection, like this String className = "Singleton"; Class aClass = (Class) 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 – Hrishikesh Mishra Apr 07 '17 at 08:37
  • 1
    @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... – Jon Skeet Apr 07 '17 at 08:41
  • 1
    @JonSkeet, it will work of egger initialization but will not lazy. try out. – Hrishikesh Mishra Apr 07 '17 at 17:54
  • 2
    @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... – Jon Skeet Apr 07 '17 at 18:55
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

ihebiheb
  • 3,673
  • 3
  • 46
  • 55
  • If you set Security manager than you are not able to call SingletonClass sc = SingletonClass.getInstance(); you will get exception every time. – Rahul Jain Aug 18 '19 at 06:18
  • 1
    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 Apr 12 '22 at 10:07
  • @Holger You can chang a `static final` field via reflection without `SecurityManager`. see [https://stackoverflow.com/a/3301720/7772947](https://stackoverflow.com/a/3301720/7772947) – xmcx Jun 16 '23 at 05:11
  • 1
    @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 Jun 16 '23 at 07:13
  • @Holger Yes, I noticed, thanks for reminding me. – xmcx Jun 16 '23 at 10:10
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.

Jordão
  • 55,340
  • 13
  • 112
  • 144
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

Vojtech Ruzicka
  • 16,384
  • 15
  • 63
  • 66
Ashish
  • 9
  • 1
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)
olive_tree
  • 1,417
  • 16
  • 23
  • Yes you can Constructor>[] constructors = Counter.class.getDeclaredConstructors(); Constructor theConstructor = constructors[0]; //suppose you have 1 constructor theConstructor.setAccessible(true); theConstructor.newInstance(); – ihebiheb Jan 14 '19 at 16:50
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
  • 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 – Ashish Agrawal Yodlee Jul 30 '17 at 05:25
  • 1
    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. – Holger Jun 16 '23 at 10:19
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();
    }

}
ABHAY JOHRI
  • 1,997
  • 15
  • 19
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

Nikhil
  • 194
  • 1
  • 8
-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
  • this is pure Singleton, This code will not break in any case like- Cloning,Serialization, Reflection. – Ashish Agrawal Yodlee Jan 27 '17 at 15:28
  • 1
    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. – Holger Apr 12 '22 at 10:20