利用反射机制破坏单例(2)

版权声明:转载请请标明出处。 https://blog.csdn.net/AnIllusion/article/details/81388273

前言

在博客上看到一篇《防止单例模式被JAVA反射攻击》的文章,通过一个静态布尔变量记录下单例类是否是第一次初始化,然后在构造函数内抛出异常来防止反射破坏。看起来合情合理,但细想,通过反射来修改那个静态变量,再调用构造函数进行实例化,同样可以破坏。按照上面的原理,我换了另一种方式实现单例类,并进行破坏。下面进行代码演示。

代码实现

单例类:

public class SingletonProPro {
    private static SingletonProPro instance;
    private SingletonProPro(){
        if(instance!=null){
            throw new RuntimeException("单例类已拦截入侵");
        }
    }

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

攻击代码:

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;

public class Main {
    public static void main(String[] args) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException, NoSuchFieldException {
        //通过调用getSingleton()方式获取对象
       SingletonProPro instance1 = SingletonProPro.getInstance();
        //通过反射方式获取对象
        Class singletonProClass = instance1.getClass();
        SingletonProPro instance2 = null;
        //修改instance为null
        Field flag = singletonProClass.getDeclaredField("instance");
        flag.setAccessible(true);
        System.out.println(flag.get(instance1));
        flag.set(instance1,null);
        System.out.println(flag.get(instance1));
        Constructor<?> constructor = singletonProClass.getDeclaredConstructor();//获取当前Class所表示类中指定的一个的构造器,和访问权限无关
        constructor.setAccessible(true);  //设置私有方法的可访问(切记,这里必须设置,否则会抛出下图的异常)
        instance2 = (SingletonProPro) constructor.newInstance();
        if(instance1==instance2){
            System.out.println("相等");
        }else {
            System.out.println("不相等");
        }
    }
}

输出结果:

SingletonProPro@14ae5a5
null
不相等

防止反射破坏单例

最简单的方法就是用static final来修饰instance并初始化:

public class SingletonPro {
    private static final SingletonPro instance = new SingletonPro();
     private SingletonPro(){
         if(instance!=null){
             throw new RuntimeException("单例模式被侵犯!");
         }
     }
     public static SingletonPro getInstance(){
         return instance;
     }
}

猜你喜欢

转载自blog.csdn.net/AnIllusion/article/details/81388273
今日推荐