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

前言

在博客上看到一篇《防止单例模式被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;
     }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值