专栏首页业余草灭霸所有单例模式,克隆、序列化、反射机制破坏7种单例模式

灭霸所有单例模式,克隆、序列化、反射机制破坏7种单例模式

单例模式实际上也不止 7 种。但是,每一种都并非安全的。今天我给大家讲一讲如何利用克隆、序列化、反射机制破坏单例模式。

我今天以痴汉式单例为例来讲,其他的单例模式破坏方式类似。

上面这个单例实现,看似很完美。但我们通过克隆、序列化、反射机制,来击破这个单例模式。

创建一个 Java 对象一般有 4 种方式:new 、克隆、序列化、反射!现在 new 这种方式不能使用了,那我们还可以使用剩下的 3 种方式!

先来看克隆!

实现 Cloneable 接口,尽管构造函数是私有,但还会创建一个对象。因为 clone 方法不会调用构造函数,会直接从内存中 copy 内存区域。所以单例模式的类是切记不要实现 Cloneable 接口。

自己运行一下,hash 值不一样,所以克隆成功了,生成了一个新对象。单例模式被成功破坏!

那么怎么抵制被克隆呢?

就是重写 clone 方法,调用 getInstance() 方法,返回已有的实例即可!

现在我们再来看序列化是如何破坏单例模式的。现在假设你的单例模式,实现了 Serializable 接口。看我下面反序列化的案例!

执行之后,hash 值不一样了,获取的对象非同一对象。结论,单例模式又被破坏了!那么怎么防止被反序列化呢?

很简单,自定义实现对象的 readResolve() 方法。

为什么实现对象的 readResolve() 方法就可以了呢?这个你可以自己 debug 一下,上面反序列化的代码。其中有一个 readOrdinaryObject 方法在做怪!

关键代码都注射的比较全,我相信你能看明白。如果还不明白,加我微信ID:xttblog。

最后,我们再来看反射是如何破坏单例模式的!

执行之后,hash 值不一样了,获取的对象非同一对象。结论,单例模式又被破坏了!那么如何解决呢?很简单,加入下面的代码。

因为执行反射会调用无参构造函数,所以上面的判断就可以起作用了!

综上所述,单例模式需要考虑,线程安全问题,效率问题,防止反射、反序列化、克隆。要不然,就有可能被黑客利用!

看到这里,有些人可能会问,这也太麻烦了,有没有更简便的方法呢?有,枚举模式。枚举类型是绝对单例的,可以无责任使用。

一个枚举,就算实现双接口,也是无论如何都无法被破坏的。枚举无法克隆,没有这样的方法。没有构造函数,会抛出异常。就算你在枚举里加了构造函数,也是一样的。对于反序列化 Java 仅仅是将枚举对象的 name 属性输出到结果中,反序列化的时候则是通过 java.lang.Enum 的 valueOf 方法来根据名字查找枚举对象。同时,编译器是不允许任何对这种序列化机制的定制的,因此禁用了 writeObject、readObject、readObjectNoData、writeReplace 和 readResolve 等方法。所以,枚举才是实现单例模式的最好方式!

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • Redis 与序列化

    序列化只是一种拆装组装对象的规则,那么这种规则肯定也可能有多种多样,比如现在常见的序列化方式有:JDK(不支持跨语言)、JSON、XML、Hessian、Kry...

    业余草
  • AD域中常见属性名词解释

    AD域中常见属性名词解释 Active Directory(AD)活动目录 schema对象模型 Organizational Unit(OU)组织...

    业余草
  • 业余草 SpringCloud教程 | 第五篇: 路由网关(zuul)(Finchley版本)

    在微服务架构中,需要几个基础的服务治理组件,包括服务注册与发现、服务消费、负载均衡、断路器、智能路由、配置管理等,由这几个基础组件相互协作,共同组建了一个简单的...

    业余草
  • django序列化时使用外键的真实值操作

    我要先序列化Module表,然后序列化Content表的时候才可以使用到Module的真实值

    砸漏
  • 牛得一批!10分钟用Python编写一个贪吃蛇小游戏

    贪吃蛇,大家应该都玩过。当初第一次接触贪吃蛇的时候 ,还是能砸核桃的诺基亚上,当时玩的不亦乐乎。今天,我们用Python编程一个贪吃蛇游戏,下面我们先看看效果:...

    龙哥
  • 10分钟用 Python 编写一个贪吃蛇小游戏

    贪吃蛇,大家应该都玩过。当初第一次接触贪吃蛇的时候 ,还是能砸核桃的诺基亚上,当时玩的不亦乐乎。今天,我们用Python编程一个贪吃蛇游戏,下面我们先看看效果:

    逆锋起笔
  • java 限流策略

    java404
  • centos 7.3 部署varnish缓存服务器

    一、简介 Varnish是高性能开源的反向代理服务器和HTTP缓存服务器,其功能与Squid服务器相似,都可以用来做HTTP缓存。可以安装 varnish 在任...

    小手冰凉
  • 投稿选刊哪家强?Web of Science神器帮你根据文章内容选期刊!

    行百里者半九十,辛辛苦苦写完了论文可不是终点,找到一个合适的期刊发表才是最终的胜利。

    百味科研芝士
  • 恢复 U 盘隐藏文件夹

    本文会经常更新,请阅读原文: https://lindexi.gitee.io/post/%E6%81%A2%E5%A4%8D-U-%E7%9...

    林德熙

扫码关注云+社区

领取腾讯云代金券