Rasika Perera Govinnage
Rasika Perera Govinnage

Reputation: 2254

How to avoid using reflections to create a new instance

I have a Singleton class which is implemented with on-demand-holder initialization. According to this article, It is still vulnerable to the reflection attacks.

How can I prevent this from java reflections to invoke private constructor and create new instances?

This is my SingletonTest class:

class SingletonTest{
    public SingletonTest(){
        System.out.println("before SingletonTest()");
        Singleton s1 = Singleton.getSingleton();
        Singleton s2 = Singleton.getSingleton();

        System.out.printf("s1 Hash: %d\n",System.identityHashCode(s1));
        System.out.printf("s2 Hash: %d\n",System.identityHashCode(s2));

        Constructor<?> con = Singleton.class.getDeclaredConstructors()[1];
        con.setAccessible(true);

        //System.out.println(con.toString());

        try {
            Singleton s3 = (Singleton) con.newInstance();
            System.out.printf("s3 Hash: %d\n",System.identityHashCode(s3));
        } catch (Exception ex) {
           ex.printStackTrace();
        }

        System.out.println("after SingletonTest()");
    }

    public static void main(String[] args){
        new SingletonTest();
    }
}

This is my Singleton class:

final public class Singleton {
    private Singleton(){
        System.out.println("Singleton created...!");
    }

    public static Singleton getSingleton(){
        return SingletonHolder.INSTANCE;
    }

    static class SingletonHolder{
            private static final Singleton INSTANCE = new Singleton();
    }

    public void doStuff(){
        System.out.println("dostuff....");
    }

}

Output:

before SingletonTest()
Singleton created...!
s1 Hash: 1924489565
s2 Hash: 1924489565
Singleton created...!
s3 Hash: 294316734
after SingletonTest()

Upvotes: 1

Views: 835

Answers (1)

Kent
Kent

Reputation: 195079

how about check and throw exception in constructor?

private Singleton(){
    if(SingletonHolder.INSTANCE !=null)
       throw new IllegalStateException("Not allowed!");
}

another possibility is, implement your singleton pattern with java Enum.

public enum Singleton {
    INSTANCE;
    public void doStuff(){...}

}

Upvotes: 1

Related Questions