懒汉式单例模式如何防止发射和反序列化漏洞

懒汉式单例模式:

/**
 * 测试饿汉式单例模式
 * Created by GQ on 2019/4/17.
 */
public class Demo02 implements Serializable{
    //类初始化时,不初始化这个对象(延时加载,真正使用的时候在创建)
    private static Demo02 demo02;

    private Demo02() {
        if(demo02 != null){ // 防止反射调用构造器的漏洞
            throw  new RuntimeException();
        }
    }

    //真正使用的时候才创建对象,资源利用率高
    //使用同步方法,并发效率较低
    public static synchronized Demo02 getInstance() {
        if (demo02 == null) {
            demo02 = new Demo02();
        }
        return demo02;
    }

    //反序列化时,如果定义了readResolve()方法,则直接返回此方法指定的对象,而不需要单独再创建新对象
    private Object readResolve() throws ObjectStreamException{
        return demo02;
    }
}

测试:

/**
 * 测试懒汉式单例模式(如何防止反射和反序列化漏洞)
 * Created by GQ on 2019/4/17.
 */
public class Client2 {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException, IOException {
        Demo02 d1 = Demo02.getInstance();
        Demo02 d2 = Demo02.getInstance();

        System.out.println(d1);
        System.out.println(d2);

        //反射漏洞(通过反射的方式直接调用私有构造器),解决方法:通过在自定义构造器中抛出异常处理
//        Class<?> c = Class.forName("com.gq.study.pattern.singleton.Demo02");
//        Constructor<Demo02> constructor = (Constructor <Demo02>) c.getDeclaredConstructor(null);
//        constructor.setAccessible(true); // 跳过安全检查,访问私有方法
//        Demo02 d3 = constructor.newInstance();
//        Demo02 d4 = constructor.newInstance();
//        System.out.println(d3);
//        System.out.println(d4);

        //反序列化漏洞(通过反序列化的方式构造多个对象),解决方法:在类中定义readResolve()方法,直接返回此方法指定的对象
        FileOutputStream fos = new FileOutputStream("E:/Idea-git/MyStudy-Java/a.txt");
        ObjectOutputStream oos = new ObjectOutputStream(fos);
        oos.writeObject(d1);
        oos.close();
        fos.close();

        FileInputStream fis = new FileInputStream("E:/Idea-git/MyStudy-Java/a.txt");
        ObjectInputStream ois = new ObjectInputStream(fis);
        Demo02 d5 = (Demo02) ois.readObject();
        System.out.println(d5);


    }
}
以下是懒汉单例模式和饿汉单例模式的异同: 相同点: 1. 都是单例模式,即保证一个类只有一个实例对象。 2. 都使用了私有的构造函数,防止外部创建实例对象。 3. 都使用了静态变量来保存实例对象。 不同点: 1. 创建对象的时机不同:饿汉在类加载时就创建了对象实例,而懒汉是在使用时才创建。 2. 线程安全性不同:饿汉天生是线程安全的,因为在类加载时就已经创建了对象实例,而懒汉需要考虑线程安全问题,可以使用synchronized关键字或者双重检查锁定等方来保证线程安全。 3. 性能不同:饿汉在类加载时就创建了对象实例,所以在访问速度和反应时间上都比懒汉快,但是如果这个实例一直没有被使用,那么就会造成内存浪费。而懒汉只有在使用时才会创建对象实例,所以在内存占用上比饿汉要低,但是在访问速度和反应时间上会稍微慢一些。 下面是懒汉单例模式的示例代码: ```python class Singleton: __instance = None def __init__(self): if Singleton.__instance != None: raise Exception("该类已经实例化过了") else: Singleton.__instance = self @staticmethod def getInstance(): if Singleton.__instance == None: Singleton() return Singleton.__instance ``` 下面是饿汉单例模式的示例代码: ```python class Singleton: __instance = Singleton() def __init__(self): if Singleton.__instance != None: raise Exception("该类已经实例化过了") else: Singleton.__instance = self @staticmethod def getInstance(): return Singleton.__instance ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值