一、反射漏洞
单例模式五种实现方法中,除了枚举式,存在反射和反序列化漏洞,即通过反射和反序列化可以破解以上几种实现方式。在这里,我们仅举例反射漏洞以及如何避免反射漏洞。
比如,懒汉式单例模式,我们可以通过反射调用私有构造器。
package com.DesignPattern;
//懒汉式单例模式
public class Singleton {
private static Singleton instance = null;
private Singleton(){
/*
//可以在构造方法中手动抛出异常,解决反射漏洞问题
if(instance!=null){
throw new RuntimeException();
}
*/
}
public static synchronized Singleton getInstance(){
if(instance==null){
instance = new Singleton();
}
return instance;
}
}
package com.DesignPattern;
import java.lang.reflect.Constructor;
public class Client {
public static void main(String[] args) {
Singleton instance = Singleton.getInstance();
Singleton instance2 = Singleton.getInstance();
System.out.println(instance);
System.out.println(instance2);
//通过反射方法调用私有构造器
Class<Singleton> clazz;
try {
clazz = (Class<Singleton>) Class.forName("com.DesignPattern.Singleton");
Constructor<Singleton> constructor = clazz.getDeclaredConstructor(null);
constructor.setAccessible(true);
Singleton instance3 = constructor.newInstance();
Singleton instance4 = constructor.newInstance();
System.out.println(instance3);
System.out.println(instance4);
} catch (Exception e) {
e.printStackTrace();
}
}
}
运行结果
二、解决方法
可以在构造方法中手动抛出异常,解决反射漏洞问题。修改后的单例模式如下
package com.DesignPattern;
//懒汉式单例模式
public class Singleton {
private static Singleton instance = null;
private Singleton(){
//可以在构造方法中手动抛出异常,解决反射漏洞问题
if(instance!=null){
throw new RuntimeException();
}
}
public static synchronized Singleton getInstance(){
if(instance==null){
instance = new Singleton();
}
return instance;
}
}
这样,因为内存中以存在该单例模式对象,所以通过反射调用私有构造器时,抛出异常