我们先来看一下序列化破坏单例模式的例子。
public class Singleton implements Serializable {
private volatile static Singleton singleton;
private Singleton() {
}
public static Singleton getSingleton() {
if (singleton == null) {
synchronized (Singleton.class) {
if (singleton == null) {
singleton = new Singleton();
}
}
}
return singleton;
}
public static void main(String[] args) throws IOException, ClassNotFoundException {
//Write Obj to file
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("tempFile"));
oos.writeObject(Singleton.getSingleton());
//Read Obj from file
File file = new File("tempFile");
ObjectInputStream ois = new ObjectInputStream(new FileInputStream(file));
Singleton newInstance = (Singleton) ois.readObject();
//判断是否是同一个对象
System.out.println(newInstance == Singleton.getSingleton());
}
这里最终输出的结果是:false,单例模式已被破坏了。那有什么办法防止序列化破坏单例模式吗?我们给Singleton再加一个方法
private Object readResolve() {
return singleton;
}
再运行一下main方法就会发现结果是:true。这是因为反序列化过程中会通过反射的方式判断序列化类是不否有readResolve方法:
readResolveMethod = getInheritableMethod(
cl, "readResolve", null, Object.class);
有readResolve的话将会调用该方法返回结果,具体源代码在ObjectInputStream中的readOrdinaryObject方法中。
if (obj != null &&
handles.lookupException(passHandle) == null &&
desc.hasReadResolveMethod())
{
Object rep = desc.invokeReadResolve(obj);
if (unshared && rep.getClass().isArray()) {
rep = cloneArray(rep);
}
if (rep != obj) {
// Filter the replacement object
if (rep != null) {
if (rep.getClass().isArray()) {
filterCheck(rep.getClass(), Array.getLength(rep));
} else {
filterCheck(rep.getClass(), -1);
}
}
handles.setObject(passHandle, obj = rep);
}
}