之前见过可以通过反射来破坏单例,和如何防止被破坏。今天讲一下序列化破坏单例。
新建类 SerializableSingletion,其实就是饿汉式单例,只是实现了Serializable接口
public class SerializableSingletion implements Serializable {
private final static SerializableSingletion SINGLETION = new SerializableSingletion();
private SerializableSingletion(){
}
public static SerializableSingletion getInstance(){
return SINGLETION ;
}
}
新建测试类
public class Test {
public static void main(String[] args) {
SerializableSingletion s1 = SerializableSingletion.getInstance() ;
SerializableSingletion s2 = null ;
try{
FileOutputStream fo = new FileOutputStream("Serializable");
ObjectOutputStream os = new ObjectOutputStream(fo);
os.writeObject(s1);
os.flush();
os.close();
FileInputStream fi = new FileInputStream("Serializable");
ObjectInputStream os2 = new ObjectInputStream(fi);
s2 = (SerializableSingletion) os2.readObject();
os2.close();
System.out.println(s1);
System.out.println(s2);
System.out.println(s1==s2);
}catch (Exception e){
e.printStackTrace();
}
}
}
通过验证,发现序列化已破坏单例。那如何去解决?在类中添加一个方法readResolve()
public class SerializableSingletion implements Serializable {
private final static SerializableSingletion SINGLETION = new SerializableSingletion();
private SerializableSingletion(){
}
public static SerializableSingletion getInstance(){
return SINGLETION ;
}
private Object readResolve(){
return SINGLETION ;
}
}
跟踪源码如下图
这个方法里面有判断是否存在readResolve方法
源码里面
case TC_OBJECT:
return checkResolve(readOrdinaryObject(unshared));
继续跟踪readOrdinaryObject方法就会发现,如下图 就会判断是否包含readResolve方法,如果有就通过反射调用方法得到返回值