如何避免使用反射来创建新实例

时间:2014-09-11 08:32:23

标签: java reflection constructor singleton

我有一个Singleton类,它是通过on-demand-holder初始化实现的。根据{{​​3}}文章,它仍然容易受到反射攻击。

如何防止java反射调用私有构造函数并创建新实例?

这是我的SingletonTest课程:

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

这是我的Singleton课程:

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....");
    }

}

输出:

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

1 个答案:

答案 0 :(得分:1)

如何检查并在构造函数中抛出异常?

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

另一种可能性是,用java Enum实现你的单例模式。

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

}