我们要创建的单例的类如下:
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());
}
}
运行结果如下:
118352462
m: class DesignMode.SingletonMode
Exception 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;
}
}
另外大家可以参考: