If I implement a Singleton either through holder idiom or double checked locking, but instead of calling 'getInstance()', use reflection to instantiate it, and then call 'getInstance()' on it, this would create two instances, breaking the pattern.
So I add a static 'counter' member to the class, increment it in the class's private constructor, and throw an exception if it crosses '1'. But in that case, if I first instantiate through reflection, nobody else would be able to call 'getInstance()' without throwing an Exception.
So how do I lazy load a Singleton yet prevent it from this attack? (I'm aware of 'Enum' pattern, but some feel that it's actually a hack. Check comments on the accepted answer of this: is this Singleton resistant to both Serialization and Reflection Attacks? and btw, my question is different).
EDIT: I think it's possible to prevent it in case of DCL, by using the static counter field, class-based synchronized constructor and assigning 'this' to the static member. However, not sure how to prevent it in case of holder idiom.
Personally I stick with Enums, but there is also the Initialization on Demand Holder (IODH) idiom
static class SingletonHolder {
static Singleton instance = new Singleton();
}
public static Singleton getInstance() {
return SingletonHolder.instance;
}
This appears in Effective Java (item 48), but I first heard of it from a post by crazy bob
http://blog.crazybob.org/2007/01/lazy-loading-singletons.html
See http://www.cs.umd.edu/~pugh/java/memoryModel/jsr-133-faq.html#dcl for lots of interesting discussion.
来源:https://stackoverflow.com/questions/10138222/java-lazy-loading-singleton-and-reflection-attack