今天在序列化反序列化的时候,发现单例模式竟然实现不了,
查了一下资料,发现反序列化由于使用了反射机制来创建一个新的对象,
导致其并没有受到单例模式的约束,今天做一个总结,以便后续查询。
有兴趣的可以从java.io.ObjectInputStream中的public final Object readObject()开始,
看一下jdk的源码:
public final Object readObject()
throws IOException, ClassNotFoundException {
return readObject(Object.class);
}
private final Object readObject(Class<?> type)
throws IOException, ClassNotFoundException
{
if (enableOverride) {
return readObjectOverride();
}
if (! (type == Object.class || type == String.class))
throw new AssertionError("internal error");
// if nested read, passHandle contains handle of enclosing object
int outerHandle = passHandle;
try {
Object obj = readObject0(type, false);
handles.markDependency(outerHandle, passHandle);
ClassNotFoundException ex = handles.lookupException(passHandle);
if (ex != null) {
throw ex;
}
if (depth == 0) {
vlist.doCallbacks();
freeze();
}
return obj;
} finally {
passHandle = outerHandle;
if (closed && depth == 0) {
clear();
}
}
}
理论上,这应该是一个jdk内的bug,不过网上也给出的解决方案,
就是在实现单例模式的类中,新增一个Object readResolve()方法(注意:这不是重写):
//the method can have private, protected and package-private access
private Object readResolve() throws ObjectStreamException{
return ourInstance; // ourInstance是该类中的静态私有变量
}
大家可以看一下java.io.Serializable中对于Object readResolve()方法的描述:
具体的测试代码,如下:
import java.io.Serializable;
import java.io.*;
/*
如何序列化单例模式?
*/
public class Solution implements Serializable {
public static void main(String[] args) throws IOException, ClassNotFoundException {
Singleton instance = Singleton.getInstance();
ByteArrayOutputStream byteArrayOutputStream = serializeSingletonInstance(instance);
Singleton singleton = deserializeSingletonInstance(byteArrayOutputStream);
Singleton singleton1 = deserializeSingletonInstance(byteArrayOutputStream);
System.out.println("检查 ourInstance:" + singleton.getInstance());
System.out.println("检查 ourInstance:" + singleton1.getInstance());
System.out.println("=========================================================");
System.out.println("检查 singleton:" + singleton);
System.out.println("检查 singleton1:" + singleton1);
}
public static ByteArrayOutputStream serializeSingletonInstance(Singleton instance) throws IOException {
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(byteArrayOutputStream);
oos.writeObject(instance);
oos.close();
return byteArrayOutputStream;
}
public static Singleton deserializeSingletonInstance(ByteArrayOutputStream byteArrayOutputStream) throws IOException, ClassNotFoundException {
ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(byteArrayOutputStream.toByteArray());
ObjectInputStream ois = new ObjectInputStream(byteArrayInputStream);
Singleton singleton = (Singleton) ois.readObject();
ois.close();
return singleton;
}
public static class Singleton implements Serializable {
private static Singleton ourInstance;
private Singleton() {
}
//新增一个Object readResolve()方法
private Object readResolve() throws ObjectStreamException{
return ourInstance;
}
public static Singleton getInstance() {
//synchronized (Singleton.class) {
if (ourInstance == null) {
ourInstance = new Singleton();
}
//}
return ourInstance;
}
}
}