5种单例模式中除了枚举式,其他都存在反射和反序列化的漏洞,下面来讲述一下:
下面是破解代码:
/**
*
* 描述:测试反射和反序列化破解单例模式Demo06
* @author cookie
*/
public class Client {
public static void main(String[] args) throws Exception {
SingletonDemo06 s1 = SingletonDemo06.getInstance();
SingletonDemo06 s2 = SingletonDemo06.getInstance();
System.out.println(s1);
System.out.println(s2);
//使用反射方式直接调用私有构造器
Class<SingletonDemo06> clazz = (Class<SingletonDemo06>) Class.forName("com.bjsxt.singleton.SingletonDemo06");
Constructor<SingletonDemo06> c = clazz.getDeclaredConstructor(null);
c.setAccessible(true);//绕过权限管理,即在true的情况下,可以通过构造函数新建对象
SingletonDemo06 s3 = c.newInstance();
SingletonDemo06 s4 = c.newInstance();
System.out.println(s3);
System.out.println(s4);
//通过反序列化的方式创建多个对象
FileOutputStream fos= new FileOutputStream("d:/a.txt");
ObjectOutputStream oos = new ObjectOutputStream(fos);
oos.writeObject(s1);
oos.close();
fos.close();
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("d:/a.txt"));
SingletonDemo06 s5= (SingletonDemo06) ois.readObject();
System.out.println(s5);
}
}
而为了防止反射和反序列化破坏单例模式,需要在单例模式中添加,具体以懒汉式为例:
/**
* 单例模式:懒汉模式 测试反射和反序列化破解单例模式
*
* @author cookie
*
*/
public class SingletonDemo06 implements java.io.Serializable {
// 类加载时,不初始化对象(延时加载:资源利用率高)
private static SingletonDemo06 instance;
private SingletonDemo06() {
if (instance != null) {
throw new RuntimeException();
}
}
// synchronized 防止并发量高的时候,出现多个对象
// 方法同步,调用效率低,
public static synchronized SingletonDemo06 getInstance() {
if (instance == null) {// 真正用的时候才加载
instance = new SingletonDemo06();
}
return instance;
}
// 在反序列化时,直接调用这个方法,返回指定的对象,无需再新建一个对象
private Object readResolve() {
return instance;
}
}
具体信息,看注释吧