虽然单例模式的构造器私有化,但通过反射和反序列化依然可以获得新的对象
(枚举由于是有JVM底层实现,反射和反序列化无法破解)。
1、反射破解单例模式,及其对策:
package com.chen.Crack_Singleton;
/**
* 饿汉式单例模式
* @author Administrator
*
*/
public class SingletonDemo01 {
// 2、创建对象
private static SingletonDemo01 instance = new SingletonDemo01();
// 1、私有化构造器
private SingletonDemo01() {
/*
* 添加过后就可以防止利用反射来破解单例模式
if(instance != null) {
throw new RuntimeException();
}
*/
}
// 3、提供静态方法获得实例对象
public static SingletonDemo01 getInstance() {
return instance;
}
}
package com.chen.Crack_Singleton;
import java.lang.reflect.Constructor;
/**
* 利用反射来破解单例模式(枚举类型实现单例模式除外)
* @author Administrator
*
*/
public class TestDemo01 {
public static void main(String[] args) throws Exception {
SingletonDemo01 instance = SingletonDemo01.getInstance();
SingletonDemo01 instance2 = SingletonDemo01.getInstance();
System.out.println(instance);
System.out.println(instance2);
// 利用反射来破解单例模式
Class<SingletonDemo01> clazz = (Class<SingletonDemo01>) Class.forName("com.chen.Crack_Singleton.SingletonDemo01");
Constructor<SingletonDemo01> c = clazz.getDeclaredConstructor(null);
c.setAccessible(true);
SingletonDemo01 instance3 = c.newInstance();
SingletonDemo01 instance4 = c.newInstance();
// 这两个对象与instance 和 instance2就不同乐,单例模式被破解
System.out.println(instance3);
System.out.println(instance4);
}
}
2、反序列化破解单例模式及其对策
package com.chen.Crack_Singleton;
import java.io.Serializable;
/**
* 懒汉式实现单例模式
* @author Administrator
*
*/
public class SingletonDemo02 implements Serializable{
private static SingletonDemo02 instance;
private SingletonDemo02() {
}
public static synchronized SingletonDemo02 getInstance() {
if(instance == null) {
instance = new SingletonDemo02();
}
return instance;
}
// 添加一个方法,避免反序列化时的漏洞
// readResolve是一个回调方法,表示在反序列化时,直接返回指定对象,不需要在创建新对象
private Object readResolve() {
return instance;
}
}
package com.chen.Crack_Singleton;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
/**
* 利用反序列化来破解单列模式
* @author Administrator
*
*/
public class TestDemo02 {
public static void main(String[] args) throws Exception {
SingletonDemo02 instance = SingletonDemo02.getInstance();
SingletonDemo02 instance2 = SingletonDemo02.getInstance();
System.out.println(instance);
System.out.println(instance2);
// 利用反序列化来破解单例模式
// 序列化操作
OutputStream os = new FileOutputStream("F:/New/a.txt");
ObjectOutputStream oos = new ObjectOutputStream(os);
oos.writeObject(instance);
oos.flush();
oos.close();
os.close();
// 反序列化操作
InputStream is = new FileInputStream("F:/New/a.txt");
ObjectInputStream ois = new ObjectInputStream(is);
SingletonDemo02 instance3 = (SingletonDemo02) ois.readObject();
System.out.println(instance3);// 与instance不同
}
}