反射如何破坏单例模式

2023-10-28

反射如何破坏单例模式

一个单例类:

public class Singleton {
    private static Singleton instance = new Singleton();   

    private Singleton() {} 

    public static Singleton getInstance() {
        return instance;
    }
}

通过反射破坏单例模式:

public class Solution {
    public static void main(String[] args) throws Exception{
    	// 第一个实例
        Singleton s1 = Singleton.getInstance();
		// 通过反射得到构造器
        Constructor<Singleton> constructor = Singleton.class.getDeclaredConstructor();
        constructor.setAccessible(true);
        // 第二个实例
        Singleton s2 = constructor.newInstance();
        System.out.println(s1.hashCode());
        System.out.println(s2.hashCode());
    }
}
输出结果:
5548145
3655388

结果表明s1和s2是两个不同的实例了。

通过反射获得单例类的构造函数,由于该构造函数是private的,通过setAccessible(true)指示反射的对象在使用时应该取消 Java 语言访问检查,使得私有的构造函数能够被访问,这样使得单例模式失效。


解决方案

如果要抵御这种攻击,要防止构造函数被成功调用两次。需要在构造函数中对实例化次数进行统计,大于一次就抛出异常

public class Singleton {
	// 统计次数
    private static int count = 0;

    private static Singleton instance = null; 
	// 在构造方法中进行次数统计与判断
    private Singleton(){
    	// 这里加锁,防止同步操作
        synchronized (Singleton.class) {
            if(count > 0){
                throw new RuntimeException("创建了两个实例");
            }
            count++;
        }

    }

    public static Singleton getInstance() {
        if(instance == null) {
            instance = new Singleton();
        }
        return instance;
    }

    public static void main(String[] args) throws Exception {

        Constructor<Singleton> constructor = Singleton.class.getDeclaredConstructor();
        constructor.setAccessible(true);
        Singleton s1 = constructor.newInstance();
        Singleton s2 = constructor.newInstance();
    }

}
执行结果:
Exception in thread "main" java.lang.reflect.InvocationTargetException
	at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
	at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
	at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
	at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
	at leetcode.Solution.main(Solution.java:38)
Caused by: java.lang.RuntimeException: 创建了两个实例
	at leetcode.Solution.<init>(Solution.java:19)
	... 5 more
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

反射如何破坏单例模式 的相关文章

随机推荐

  • BUUCTF WEB [极客大挑战 2019]LoveSQL1

    首先查看源码 没什么发现 继续尝试万能密码 成功登录 MD5解密无果 看起来不是 因为题目提示SQL 所以试一下注入 使用他给的密码登录admin 在url中使用order by 查询到有3个字段 直接使用union select 1 2
  • Linux系统编程--进程编程

    进程相关概念 问1 什么是程序 什么是进程 有什么区别 程序是静态的概念 gcc xxx c o pro 磁盘中生成pro文件 叫做程序 进程是程序的一次运行活动 通俗点意思是程序跑起来了 系统中就多了一个进程 问2 如何查看系统中有哪些进
  • SpringSecurity------WebSecurityConfiguration配置类

    SpringSecurity WebSecurityConfiguration配置类 一 WebSecurityConfiguration是怎样被加载的 二 WebSecurityConfiguration主要做了什么 三 WebSecur
  • moviepy音视频剪辑:使用mask遮罩实现视频叠加透明效果

    前往老猿Python博客 https blog csdn net LaoYuanPython 一 引言 在 moviepy音视频剪辑 mask clip遮罩剪辑 遮片 蒙版的作用以及其包含的构成内容 中介绍 mask遮罩是一种只有灰度值的像
  • spring boot 未知问题

    在STS中创建spring boot项目时pom文件常常 出现红叉 点击它显示 unknown error 使用spring boot 2 1 5 RELEASE同样会出现红叉 但这两个版本均能正常使用 但看着非常不顺眼 使用2 1 4 R
  • VUE element-ui之el-form表单非必填内容格式校验

    需求 手机号码非必填 校验其格式 实现方法
  • IDEA设置Properties配置文件的编码

    IDEA设置Properties配置文件的编码 1 idea已经设置统一编码UTF 8 没有设置过的同学可以设置下 IDEA正确设置编码统一为UTF 8 但是通过spring获取 properties中的中文还是会乱码 所以要按照以下配置
  • ttf字体

    TTF TrueTypeFont 是Apple公司和Microsoft公司共同推出的字体文件格式 随着windows的流行 已经变成最常用的一种字体文件表示方式 TTF是字库中的一种 应用范围非常广 1 更换字体 如何将TTF文件导入到你的
  • js贪心算法

    贪心算法是指在对问题求解时 总是做出在当前看来是最好的选择 也就是说 不从整体最优上加以考虑 它所做出的仅是在某种意义上的局部最优解 贪心算法没有固定的算法框架 算法设计的关键是贪心策略的选择 必须注意的是 贪心算法不是对所有问题都能得到整
  • 沉浸式翻译 – 支持 PDF、EPUB、网页,可同时显示原文与译文的双语翻译工具

    使用的理由 自从谷歌翻译不再对大陆用户提供服务后 内心是一阵酸痛的 毕竟我认识单词单词不认识我啊 这简直是天书一般的存在 期间网络中的很多大神也是推荐了不少方法让我再次拥抱谷歌翻译 比如教我修改 host 文件什么的 但这毕竟也不是长久之计
  • 如何通俗理解扩散模型?

    扩散模型 Diffusion Model 是一类十分先进的基于扩散思想的深度学习生 成模型 生成模型除了扩散模型之外 还有出现较早的 VAE Variational Auto Encoder 变分自编码器 和 GAN Generative
  • 在Ubuntu上安装GNU radio

    首先 我不得不说在Ubuntu上面安装GNU radio 对于初学者来说还真不是一件简单的事情 本人从最开始的一点点都不懂到最后熟悉 了解 成功安装GNU radio整整花了大概3天的时间 现在把自己在这个过程中学到的东西分享给大家 希望对
  • db2死锁分析与处理

    在数据库中 锁的主要功能是为了控制并发数据的完整性而引入的机制 在并发应用中出现锁现象并不可怕 锁现象通常分为死锁和锁等待两种情形 死锁是因为两个并发的进程或者线程同时各自占有一个资源 又需要占有对方资源 但又都各不相让造成的 这通常是因为
  • LeetCode题目笔记——6362. 合并两个二维数组 - 求和法

    文章目录 题目描述 题目链接 题目难度 简单 方法一 常规双指针遍历 代码 Python 方法二 字典 哈希表 代码 Python 总结 题目描述 给你两个 二维 整数数组 nums1 和 nums2 nums1 i idi vali 表示
  • JAVA基础总结

    我们能活多少年并不重要 我们的生命无非是有无数的瞬间组成的 我们永远无法知道 它会发生在何时何处 但这些瞬间会伴我们一生 在灵魂上印上永远的印记 不死法医 Java 的数据类型 八大基本类型 整数型 byte int short long
  • 机器人--基础知识

    目录 0 姿态变换与坐标变换 1 机器人齐次变换 2 贝叶斯概率模型 0 姿态变换与坐标变换 机器人中的坐标系 它是一组基 表示为一个其次变换矩阵 一般为4阶 包含了当前坐标系与其他坐标系的旋转 平移关系 所以一般而言机器人的姿态变换就是坐
  • python爬取有声小说

    前言 我写过很多爬取有声小说的案例 有些是因为审核的原因 不能放出来 在加上平时就喜欢听有声小说 但是现在的有声小说大部分都收费了 作为一个玩爬虫的 收费听小说是自己不能忍的 最近发现了一部小说通过分析 是不需要付费可以爬取下来的 特把这次
  • Vue第一篇:最基本的概念(背诵专用)

    一 背诵目录结构 1 创建一个Vue实例 2 Vue选项名称 8种 3 vue实例挂载元素 4 vue实例绑定数据 5 vue js提供的实例属性和方法 6 数据绑定 1 文本插值 2 输出HTML内容 3 绑定HTML属性 4 绑定HTM
  • git大文件传输(LFS)及超限解决

    git lfs install 安装git lfs 一个账号只用安装一次 git lfs track gif eg 追踪记录 gif类型的文件 根据自己需要想要上传什么类型的文件 就追踪什么类型的文件 git lfs track demo
  • 反射如何破坏单例模式

    反射如何破坏单例模式 一个单例类 public class Singleton private static Singleton instance new Singleton private Singleton public static