1 案例



熟悉的 DCL 单例实现
防止Java序列化/反射破坏单例模式的解决方案_构造器



测试类防止Java序列化/反射破坏单例模式的解决方案_序列化_02



可见对​​Singleton​​​的序列化、反序列化得到的对象是一个新的对象,说明破坏了​​Singleton​​的单例性。

2 序列化破坏单例的源码分析

看关键代码​​readOrdinaryObject​



该处创建的​​obj​​就是本方法要返回的对象
防止Java序列化/反射破坏单例模式的解决方案_构造器_03



isInstantiable:若一个​​serializable/externalizable​​的类可在运行时被实例化,则该方法返回true



desc.newInstance:该方法通过反射调用无参构造器生成一个对象



所以在序列化的底层是会通过反射调用无参构造器创建一个新的对象的。

3 避免序列化破坏单例

3.1 ObjectInputStream#readObject

防止Java序列化/反射破坏单例模式的解决方案_反序列化_04


  • ​hasReadResolveMethod​​​:若实现了​​serializable​​​/​​externalizable​​​接口的类中包含​​readResolve​​,则返回true
  • ​invokeReadResolve​​:通过反射调用要被反序列化的类的readResolve方法

3.2 解决方案

在Singleton类中定义​​readResolve​​即可:

防止Java序列化/反射破坏单例模式的解决方案_构造器_05