美文网首页
避免单例模式被反序列化和反射创建出新的实例

避免单例模式被反序列化和反射创建出新的实例

作者: 缓慢移动的蜗牛 | 来源:发表于2018-07-04 10:31 被阅读0次

双重检测锁的单例模式

package com.nanc;

import java.io.ObjectStreamException;
import java.io.Serializable;

public class Singleton implements Serializable {

    private static final long serialVersionUID = -7357258499538582501L;

    private static volatile Singleton instance;
    private String name;

    private Singleton(){
        //防止使用反射的方式创建实例
        if (null != instance) {
            throw new RuntimeException("");
        }
    }

    private Singleton(String name) {
        //防止使用反射的方式创建实例
        if (null != instance) {
            throw new RuntimeException("");
        }

        System.out.println("调用有参数的构造器");
        this.name = name;
    }

    public static Singleton getInstance(String name) {
        if (null == instance) {
            synchronized(Singleton.class){
                if (null == instance) {
                    instance = new Singleton(name);
                }
            }
        }
        return instance;
    }

    /**
     * 提供readResolve()方法
     *  当JVM反序列化地恢复一个新对象时,
     *  系统会自动调用这个readResolve()方法返回指定好的对象,
     *  从而保证系统通过反序列化机制不会产生多个java对象
     * @return
     * @throws ObjectStreamException
     */
    private Object readResolve()throws ObjectStreamException {
        return instance;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

使用反射获取实例测试

public class SingletonTest {

   public static void main(String[] args) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
      Singleton s = Singleton.getInstance("hello");
      Class cls = Singleton.class;
      Constructor con = cls.getDeclaredConstructor();
      con.setAccessible(true);

      Singleton s2 = (Singleton) con.newInstance();
      System.out.println(s2.getName());

   }
}

使用反序列化获取实例测试

public class SingletonTest {

   public static void main(String[] args) throws IOException {
      Singleton s = Singleton.getInstance("Hello");
      System.out.println("Wolf对象创建完成");

      Singleton s2;

      ObjectOutputStream oos = null;
      ObjectInputStream ois = null;

      try {
         oos = new ObjectOutputStream(new FileOutputStream("a.bin"));
         ois = new ObjectInputStream(new FileInputStream("a.bin"));

         oos.writeObject(s);
         oos.flush();

         TimeUnit.SECONDS.sleep(1);

         //不会调用该类的构造器
         s2 = (Singleton) ois.readObject();

         //是否是同一个对象
         System.out.println(System.identityHashCode(s));
         System.out.println(System.identityHashCode(s2));
      } catch (Exception e) {
         e.printStackTrace();
      }finally {
         if (oos != null) {
            oos.close();
         }
         if (ois != null) {
            ois.close();
         }
      }
   }
}

相关文章

  • Java-单例模式

    单例模式:顾名思义,表示这个类只有一个实例存在。 单例模式的好处:避免实例对象被重复创建,减少每次创建实例的时间,...

  • 避免单例模式被反序列化和反射创建出新的实例

    双重检测锁的单例模式 使用反射获取实例测试 使用反序列化获取实例测试

  • 深度解析单例与序列化之间的爱恨情仇~

    本文将通过实例+阅读Java源码的方式介绍序列化是如何破坏单例模式的,以及如何避免序列化对单例的破坏。 单例模式,...

  • 单例与序列化的那些事儿

    本文将通过实例+阅读Java源码的方式介绍序列化是如何破坏单例模式的,以及如何避免序列化对单例的破坏。 单例模式,...

  • 反射破坏单例模式(静态内部类)

    java反射,破坏单例模式 静态内部类 反射实例化单例

  • Java 单例模式 (Singleton Pattern)

    分享两个典型的Java单例模式写法: 第一种: 双检锁机制实现单例模式 -- 较复杂,且无法避免使用反射和反序列化...

  • 设计模式-创建型

    一,单例模式 单例模式(Singleton Pattern):主要是为了避免因为创建了多个实例造成资源的浪费,且多...

  • 设计模式

    1 单例设计模式 单例模式主要是为了避免因为创建多个实例造成的资源浪费,且多个实例由于多次调用容易导致结果出现错误...

  • 安卓之单例模式讲解

    为什么我们要使用单例模式呢? 单例模式主要是为了避免因为创建太多的实例从而造成资源浪费,而且多个实例的多次调用可能...

  • 枚举单例原理

    单例实现思路 1、构造方法私有化;2、实例化的变量引用私有化;3、获取实例的方法共有。 优点:避免反射、序列化问题

网友评论

      本文标题:避免单例模式被反序列化和反射创建出新的实例

      本文链接:https://www.haomeiwen.com/subject/nbteuftx.html