序列化反序列化破坏单例模式的原因及解决方案(以懒汉式为例)

普通懒汉式

/**
 * 懒汉式单例
 */
@Data
public class LazySingle implements Serializable {
    private String singleName;
    //volatile,确保本条指令不会因编译器的优化而省略,且要求每次直接读值
    private static volatile LazySingle lazySingle=null;

    //解决多线程不能保证单例情况   **Double Check(双重校验) + Lock(加锁)**
    public static LazySingle getInstance() {
        if(lazySingle==null){// 线程A和线程B同时看到singleton = null,如果不为null,则直接返回singleton
            synchronized (LazySingle.class) {// 线程A或线程B获得该锁进行初始化
                if(lazySingle == null){// 其中一个线程进入该分支,另外一个线程则不会进入该分支
                    lazySingle = new LazySingle();
                }
            }

        }
        return lazySingle;
    }

使用序列化与反序列化破坏单例模式

 try {
            File file = new File("Singleton.txt");
            //创建输出流
            ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(file));
            //将单例对象写到文件中  序列化
            oos.writeObject(LazySingle.getInstance());
            //从文件读取单例对象
            ObjectInputStream ois = new ObjectInputStream(new FileInputStream(file));
            //反序列化得到对象lazySingle
            LazySingle lazySingle=(LazySingle)ois.readObject();
            System.out.println(lazySingle==LazySingle.getInstance()); //false
        } catch (Exception e) {
            e.printStackTrace();
        }

原因

通过阅读源码发现,反序列化方法readObject()readObject0()中如果是Object对象则调用readOrdinaryObject(),该方法首先会通过一个三目运算来创建序列化的对象。如果这个对象能实例化就创建一个新对象

obj = desc.isInstantiable() ? desc.newInstance() : null;

解决方法

在通过三目运算创建了对象之后,还会去找这个对象里是否有readResolve()方法,如果有,则通过这方法返回对象。

    if (obj != null &&handles.lookupException(passHandle) == null && desc.hasReadResolveMethod()){
    	 Object rep = desc.invokeReadResolve(obj);
   }

所以只需要在单例类中新增readResolve()方法即可

	public Object readResolve() {
	    return getInstance();
	}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

远离bug,珍爱头发

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值