【问题标题】:How to avoid using reflections to create a new instance如何避免使用反射创建新实例
【发布时间】:2014-09-11 08:32:23
【问题描述】:

我有一个Singleton 类,它是通过按需初始化实现的。根据this 的文章,它仍然容易受到反射攻击。

如何防止 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()

【问题讨论】:

    标签: java reflection constructor singleton


    【解决方案1】:

    在构造函数中检查并抛出异常怎么样?

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

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

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

    【讨论】:

    • 谢谢它正在工作:);我尝试了java.lang.InstantiationException,这不是 RunTimeException。我在某处读到你可以使用 SecurityManager 控制它。有什么想法吗?
    • @tiriboy 扔InstantiationError 怎么样?或者你希望它是RuntimeEx,只是new RuntimeException()?还是我没找到你?
    • 是的,它似乎更具自我描述性。 tnx.
    • 在调用构造函数之前你仍然可以set INSTANCE to null using reflection。
    • @FlorentBayle:但它声明为final O.o 任何解决方案?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-10-29
    • 2018-03-29
    • 2016-04-16
    相关资源
    最近更新 更多