被破坏的单例模式

原创 2018年04月15日 13:51:45
被破坏的单例模式


我们知道饿汉单例天生是线程安全的,但是通过其他途径单例模式是可以被破坏的。懒汉亦如此。


1、通过反射来破解单例模式

	public class Eagersingleton implements Serializable {

		private static final long serialVersionUID = 888L;
		private static Eagersingleton m_instance = new Eagersingleton();// 初始化时已经自行实例化

		// 私有默认构造方法
		private Eagersingleton() {
		}

		// 静态工厂方法
		public static Eagersingleton getInstance() {
			return m_instance;
		}
	}
	public class Test1 {

		public static void main(String[] args) throws NoSuchMethodException,
				SecurityException {
			// 获取单例对象
			Eagersingleton instance = Eagersingleton.getInstance();
			Eagersingleton instance2 = null;
			try {
				Class cls = Eagersingleton.class;
				Constructor constructor = cls.getDeclaredConstructor(null);
				// 关掉安全检查,可以调用私有构造器
				constructor.setAccessible(true);
				// 通过反射得到一个对象
				instance2 = (Eagersingleton) constructor.newInstance(null);
			} catch (InstantiationException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (IllegalAccessException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (IllegalArgumentException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (InvocationTargetException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			System.out.println(instance);
			System.out.println(instance2);
		}
	}
    
打印出来的结果不一样,说明这两个对象就是不同的对象,这样就破解了单例模式。

解决方案:避免反射


反射是通过它的Class对象来调用构造器创建出新的对象,我们只需要在构造器中手动抛出异常,导致程序停止就可以达到目的了。

2、通过序列化和反序列化破解单例

	public class Test2 {

		public static void main(String[] args) throws FileNotFoundException,
				ClassNotFoundException {
			// 获取单例对象
			Eagersingleton instance = Eagersingleton.getInstance();

			// 通过反序列化读取对象
			Eagersingleton instance2 = null;
			try {
				ObjectOutputStream oossStream = new ObjectOutputStream(
						new FileOutputStream("D:/EagersingletonTest.txt"));

				// 通过序列化把对象写到文件中
				oossStream.writeObject(instance);
				oossStream.flush();
				oossStream.close();
				// 读取文件的对象
				ObjectInputStream ois = new ObjectInputStream(new FileInputStream(
						"D:/EagersingletonTest.txt"));

				instance2 = (Eagersingleton) ois.readObject();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}

			System.out.println(instance);
			System.out.println(instance2);
		}
	}

打印出来的结果不一样,说明这两个对象就是不同的对象,破解了单例模式。

解决方案:避免序列化

readResolve()这个方法是基于回调的,反序列化时,如果定义了readResolve()则直接返回此方法指定的对象,而不需要在创建新的对象。









每天努力一点,每天都在进步。
版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/dingjianmin/article/details/79948677

如何破坏单例模式?如何防止?

前几天看到一道面试题,问的是单例的模式书写以及单例模式能被破坏吗?如何被破坏?如何防止?...
  • MakeContral
  • MakeContral
  • 2017-12-04 20:28:31
  • 179

如何防止单例模式被JAVA反射攻击

单例模式相信大家都知道,用过的人不在少数。之前写过一篇博文《singleton模式四种线程安全的实现》(参见:http://blog.csdn.net/u013256816/article/detai...
  • u013256816
  • u013256816
  • 2016-01-15 18:29:00
  • 10129

反射 序列化 克隆对单例模式的破坏

本文主要总结一下单例模式,以及其他对象创建方式可能对单例模式的破坏和解决方式。 现在看一个问题:对象的创建方式有哪几种? 四种:new 、克隆、序列化、反射。...
  • chao_19
  • chao_19
  • 2016-04-10 15:03:52
  • 2160

java反射技术破坏单例模式

一、 Java中的反射技术可以获取类的所有方法、成员变量、还能访问private的构造方法,这样一来,单例模式中用的私有构造函数被调用就会产生多个实例,编写代码测试一下。 package test;...
  • lws332969674
  • lws332969674
  • 2012-10-29 21:07:21
  • 9466

如何粗鲁地破坏一个单例模式

单例模式是如何被破坏的单例模式的定义: 单例模式,是一种常用的软件设计模式。在它的核心结构中只包含一个被称为单例的特殊类。通过单例模式可以保证系统中,应用该模式的类一个类只有一个实例。即一个类只有一...
  • qq_40396127
  • qq_40396127
  • 2017-12-13 17:56:31
  • 160

反射如何破坏单例模式

一个单例类:public class Singleton { private static Singleton instance = new Singleton(); privat...
  • u011298387
  • u011298387
  • 2016-11-11 17:31:42
  • 644

让我们来破坏单例模式

通常情况下单例模式只能生成唯一的对象,但是有些情况可以破坏单例模式,一起学习一下吧...
  • dreamrealised
  • dreamrealised
  • 2013-11-14 13:31:06
  • 2256

使用反射破坏和管理单例模式

Java中可以使用反射来破坏了单例模式,也可以使用反射来管理单例模式。
  • xuepiaohan2006
  • xuepiaohan2006
  • 2014-05-05 17:23:40
  • 1034

Java设计模式(一):单例模式,防止反射和反序列化漏洞

一、懒汉式单例模式,解决反射和反序列化漏洞 package com.iter.devbox.singleton; import java.io.ObjectStreamException; impo...
  • hardwin
  • hardwin
  • 2016-05-22 22:49:18
  • 4246

单例的获取and序列化和反序列化破坏单例的原因及解决方法

单例模式就是在整个全局中(无论是单线程还是多线程),该对象只存在一个实例,而且只应该存在一个实例,没有副本(副本的制作需要花时间和空间资源)。在它的核心结构中只包含一个被称为单例的特殊类。通过单例模式...
  • chy6575
  • chy6575
  • 2016-04-05 11:38:23
  • 1152
收藏助手
不良信息举报
您举报文章:被破坏的单例模式
举报原因:
原因补充:

(最多只允许输入30个字)