防止单例模式被攻击的一个Demo

来源:互联网 发布:走淘宝的微商 编辑:程序博客网 时间:2024/05/17 03:04

我们要创建的单例的类如下:

package DesignMode;public class SingletonMode{    private static volatile SingletonMode single = null;    private static boolean flag = true;    private SingletonMode()    {        synchronized(SingletonMode.class)        {            if(flag)            {                flag = false;            }else            {                throw new RuntimeException("单例模式被攻击!!!");            }        }    }    public static SingletonMode getInstance()    {        if (single == null)        {            // 锁的范围缩小            synchronized (SingletonMode.class)            {                if (single == null)                {                    single = new SingletonMode();                }            }        }        return single;    }}

我们的攻击类如下:

package DesignMode;import java.lang.reflect.Constructor;import java.lang.reflect.InvocationTargetException;public class attackSingleton{    public static void main(String[] args) throws NoSuchMethodException, SecurityException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException    {        Class<?> classType = SingletonMode.class;        Constructor<?> c = classType.getDeclaredConstructor(null);        c.setAccessible(true);        SingletonMode m = (SingletonMode)c.newInstance();        System.out.println(m.hashCode());        System.out.println("m: "+m.getClass());        SingletonMode n = SingletonMode.getInstance();        System.out.println(m == n);        System.out.println(n.hashCode());        System.out.println("n: "+n.getClass());    }}

运行结果如下:

118352462m: class DesignMode.SingletonModeException in thread "main" java.lang.RuntimeException: 单例模式被攻击!!!    at DesignMode.SingletonMode.<init>(SingletonMode.java:18)    at DesignMode.SingletonMode.getInstance(SingletonMode.java:32)    at DesignMode.attackSingleton.main(attackSingleton.java:19)

不过上面这个Demo只是防止被攻击,如果一个线程通过反射创造出一个实例对象之后,其他线程就无法通过getInstance()方法得到这个实例对象了。因此我们不能再用懒汉式单例创建,而应该改用饿汉式。

//饿汉式单例类.在类初始化时,已经自行实例化 public class Singleton1 {    private Singleton1() {}    private static final Singleton1 single = new Singleton1();    //静态工厂方法     public static Singleton1 getInstance() {        return single;    }}

另外大家可以参考:

如何防止单例模式被攻击。

0 0