Java Singleton

Java的单例模式在Effective Java里面有权威的做法,就是用Enum。这是最完美的做法。它利用Java自身语言机制保证了内存中只有一份拷贝,同时它也让那些想通过Reflection + setAccessable()的攻击单例的做法失败。

下面列出来4中Singleton实现,然后分别用Reflection + SetAccessable()来攻击单例,如果能创建出两份单例,就认为攻击成功。

/*
 * Singleton in a holder has following advantages:
The key of this implementation relies on the very well specified initialization phase of execution of the Java Virtual Machine.

When the Singleton class is loaded by the JVM the class is initialized but since it doesn’t have any static variables to initialize then it completes without any additional steps executed. The static class definition InstanceHolder that is defined inside Singleton class in line 4 is not intialized until the JVM determines that InstanceHolder must be executed. The static class InstanceHolder is executed only when the static method getInstance is invoked on the class Singleton, and only then the JVM will load and intialize the InstanceHolder class. The intialization of the HolderInstance class then results in static variable ‘instance’ in line 5 being initialized by executing the private constructor for the outer class Singleton. Since the class initialization is guaranteed to be serial (non-concurrent) then no further synchronization is required in the static getInstance method during load and initialization time and since the intialization phase sets the static var singleton in a serial operation all subsequent concurrent invocations of the getInstance method will return the correctly initialized singleton without incurring in synchronization overhead.

The initialization on demand class holder singleton is a more efficient and thread-safe implementation in the Java language.
 */
public class HolderSingleton {
    // Private constructor prevents instantiation from other classes
    private HolderSingleton() {
        System.out.println("Inside HolderSingleton(): Singleton instance is being created.");
    }

    /**
     * SingletonHolder is loaded on the first execution of
     * Singleton.getInstance() or the first access to SingletonHolder.INSTANCE,
     * not before.
     */
    private static class SingletonHolder {
        public static final HolderSingleton instance = new HolderSingleton();
    }

    public static HolderSingleton getInstance() {
        return SingletonHolder.instance;
    }

}



/**
 * Lazy initialization singleton
 */
public class LazySingleton {
    private static LazySingleton _instance;

    private LazySingleton() {
        System.out.println("Inside LazySingleton(): Singleton instance is being created.");
    }
    
    public static synchronized LazySingleton getInstance() {
        if (_instance == null) {
            _instance = new LazySingleton();
        }
        return _instance;
    }

}


/**
 * Most frequently used singleton -- traditional singleton
 */
public class TraditionSingleton {
    private static final TraditionSingleton instance = new TraditionSingleton();

    // Private constructor prevents instantiation from other classes
    private TraditionSingleton() {
        if (instance != null) {
            //throw new IllegalStateException("Inside JavaSingleton(): JavaSingleton " + "instance already created.");
        }
        System.out.println("Inside TraditionSingleton(): Singleton instance is being created.");

    }

    public static TraditionSingleton getInstance() {
        return instance;
    }

}


/**
 * Singleton recommended by Effective Java 2nd Edition. Enum singleton which need JDK 1.6 or more higher version
 */
public enum EnumSingleton {
    INSTANCE;
    EnumSingleton(){
        System.out.println("Inside EnumSingleton(): Singleton instance is being created.");
    }
}

测试程序如下:

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;


public class ReflectionAttack {
    public static void main(String args[]) 
    throws IllegalArgumentException, 
            InstantiationException, 
            IllegalAccessException, 
            InvocationTargetException, 
            SecurityException, 
            NoSuchMethodException {
        attackTraditionSingleton();
        attackLazy();
        attackHolder();
        attackEnum();
    }
    
    private static void attackTraditionSingleton() 
    throws SecurityException, NoSuchMethodException, IllegalArgumentException, InstantiationException, IllegalAccessException, InvocationTargetException {
        Class<TraditionSingleton> clazz = TraditionSingleton.class;
        Constructor<TraditionSingleton> cons = clazz.getDeclaredConstructor();
        cons.setAccessible(true);
        TraditionSingleton s2 = cons.newInstance();
    }
    
    private static void attackLazy() throws IllegalArgumentException, InstantiationException, IllegalAccessException, InvocationTargetException, SecurityException, NoSuchMethodException {
        Class<LazySingleton> clazz = LazySingleton.class;
        Constructor<LazySingleton> cons = clazz.getDeclaredConstructor();
        cons.setAccessible(true);
        LazySingleton s1 = cons.newInstance();
        s1 = LazySingleton.getInstance();
    }
    
    private static void attackHolder() throws SecurityException, NoSuchMethodException, IllegalArgumentException, InstantiationException, IllegalAccessException, InvocationTargetException {
        Class<HolderSingleton> clazz = HolderSingleton.class;
        Constructor<HolderSingleton> cons = clazz.getDeclaredConstructor();
        cons.setAccessible(true);
        HolderSingleton s = cons.newInstance();
        s = HolderSingleton.getInstance();
    }
    
    private static void attackEnum() throws SecurityException, NoSuchMethodException, IllegalArgumentException, InstantiationException, IllegalAccessException, InvocationTargetException {
        Class<EnumSingleton> clazz = EnumSingleton.class;
        Constructor<EnumSingleton> cons = clazz.getDeclaredConstructor();
        cons.setAccessible(true);
        EnumSingleton s = cons.newInstance();
    }
}


运行结果如下:

Inside TraditionSingleton(): Singleton instance is being created.
Inside TraditionSingleton(): Singleton instance is being created.
Inside LazySingleton(): Singleton instance is being created.
Inside LazySingleton(): Singleton instance is being created.
Inside HolderSingleton(): Singleton instance is being created.
Inside HolderSingleton(): Singleton instance is being created.
Exception in thread "main" java.lang.NoSuchMethodException: net.local.singleton.EnumSingleton.<init>()
 at java.lang.Class.getConstructor0(Class.java:2706)
 at java.lang.Class.getDeclaredConstructor(Class.java:1985)
 at net.local.attack.ReflectionAttack.attackEnum(ReflectionAttack.java:51)
 at net.local.attack.ReflectionAttack.main(ReflectionAttack.java:22)

显然,只有Enum Singleton经受得起攻击,而且是最简单、最高效的实现。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值