Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/design-patterns/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 使用反射防止单体破裂_Java_Design Patterns - Fatal编程技术网

Java 使用反射防止单体破裂

Java 使用反射防止单体破裂,java,design-patterns,Java,Design Patterns,我遇到了下面的示例,其中可以使用反射实例化单例类。代码如下所示 public class SingletonExploitationExample { public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {

我遇到了下面的示例,其中可以使用反射实例化单例类。代码如下所示

public class SingletonExploitationExample {

    public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {
        MySingleTon.getInstance();
        Constructor<MySingleTon> constructor = MySingleTon.class.getDeclaredConstructor();
        constructor.setAccessible(true);
        MySingleTon obj1 = constructor.newInstance();
        MySingleTon obj2 = constructor.newInstance();
        MySingleTon obj3 = constructor.newInstance();
        obj1.printN();
    }
}

final class MySingleTon {
    private static MySingleTon instance = null;

    private static int count = 0;
    private MySingleTon(){
        count++;
    }

    public void printN(){
        System.out.println(count);
    }

    public static MySingleTon getInstance(){
        if(instance == null){
            synchronized (MySingleTon.class){
                if(instance == null){
                    instance = new MySingleTon();
                }

            }
        }
        return instance;
    }
}
公共类Singleton漏洞利用示例{
publicstaticvoidmain(字符串[]args)抛出ClassNotFoundException、IllegalAccessException、InstantiationException、NoSuchMethodException、InvocationTargetException{
MySingleTon.getInstance();
构造函数=MySingleTon.class.getDeclaredConstructor();
constructor.setAccessible(true);
MySingleTon obj1=constructor.newInstance();
MySingleTon obj2=constructor.newInstance();
MySingleTon obj3=constructor.newInstance();
obj1.printN();
}
}
米辛格尔顿期末班{
私有静态MySingleTon实例=null;
私有静态整数计数=0;
二等兵迈辛格尔顿(){
计数++;
}
公共无效打印n(){
系统输出打印项次(计数);
}
公共静态MySingleTon getInstance(){
if(实例==null){
已同步(MySingleTon.class){
if(实例==null){
instance=new MySingleTon();
}
}
}
返回实例;
}
}

是否有任何方法可以避免这种情况,或者使单个实例只有一个实例(同时使用反射,用户不应该能够实例化新对象)?

是的,使用
enum
s

枚举使强大的线程安全,“类加载器安全”的单例,不能通过反射初始化

这里有一个例子

enum Foo {
    INSTANCE;
}

Class<?> fooClass = Foo.class;
Constructor<?> c = fooClass.getDeclaredConstructors()[0];
c.setAccessible(true);
Foo f = (Foo)c.newInstance();

是,使用
enum
s

枚举使强大的线程安全,“类加载器安全”的单例,不能通过反射初始化

这里有一个例子

enum Foo {
    INSTANCE;
}

Class<?> fooClass = Foo.class;
Constructor<?> c = fooClass.getDeclaredConstructors()[0];
c.setAccessible(true);
Foo f = (Foo)c.newInstance();


让我们不要忘记反序列化作为攻击向量。Enum也可以避免这种情况。嗯,反射有点像客厅里的把戏。你已经可以用它做很多事情了。但是,如果您使用
sun.misc.Unsafe.allocateInstance(Foo.class)来破解重炮这可能很好用。因此,假设您可以在Java中对实际敏感信息保密不是一个好主意。@robin阅读我的答案。如上所述使用的枚举是单例。如果希望保持相同的语法等,可以添加一个方便的方法
getInstance
,以返回唯一的实例(
instance
),但本质上只需要将
MySingleton
重构为
enum
@Mena,“剩下的代码是关于单例本身的,因此与enum无关,对吗?”错误的枚举是实现单例反模式的标准和最佳方式。担心
不安全的问题是没有意义的。您可以控制类加载和安全管理器,在这种情况下,您可以“禁止”
不安全的
,也可以不这样做,攻击者可以在类加载期间截取并修改您的字节码。安全代码一般只在控制环境但强制运行潜在不安全代码的上下文中是有意义的。我们不要忘记反序列化作为攻击向量。Enum也可以避免这种情况。嗯,反射有点像客厅里的把戏。你已经可以用它做很多事情了。但是,如果您使用
sun.misc.Unsafe.allocateInstance(Foo.class)来破解重炮这可能很好用。因此,假设您可以在Java中对实际敏感信息保密不是一个好主意。@robin阅读我的答案。如上所述使用的枚举是单例。如果希望保持相同的语法等,可以添加一个方便的方法
getInstance
,以返回唯一的实例(
instance
),但本质上只需要将
MySingleton
重构为
enum
@Mena,“剩下的代码是关于单例本身的,因此与enum无关,对吗?”错误的枚举是实现单例反模式的标准和最佳方式。担心
不安全的问题是没有意义的。您可以控制类加载和安全管理器,在这种情况下,您可以“禁止”
不安全的
,也可以不这样做,攻击者可以在类加载期间截取并修改您的字节码。一般来说,安全代码只有在您控制环境但被迫在其中运行潜在不安全代码的情况下才有意义。好吧,一般的答案将倾向于否定。但您能否补充一下为什么需要这种功能?您的用例是什么?只是好奇。@好奇只是好奇,想知道有没有办法?:)只是不要使用单例。@LewBloch为什么?因为它们很少是必需的。好的,我明白了​, 但根据我的经验,几乎没有人正确地使用singleton,而且几乎总是在不必要的时候使用。对于大多数用例,我们不需要在代码中强制执行singleton属性。当我们确实需要时,而且有时确实会发生,那么
enum
几乎肯定是正确的实现。好的,一般的答案将倾向于否定。但是您能否补充一下为什么需要这种功能?您的用例是什么?只是好奇。@好奇只是好奇,想知道有没有办法?:)只是不要使用单例。@LewBloch为什么?因为它们很少是必需的。好的,我明白了​, 但根据我的经验,几乎没有人正确地使用singleton,而且几乎总是在不必要的时候使用。对于大多数用例,我们不需要在代码中强制执行singleton属性。当我们确实需要并且有时确实会发生时,
enum
几乎肯定是正确的实现。