What are the different ways we can break a singleton pattern in Java
java, singleton
Solution
Starting with your given code, "Double-Checked Locking" can be broken at some environment, When run on a system using the Symantec JIT, it doesn't work. In particular, the Symantec JIT compiles
singletons[i].reference = new Singleton();
to the following (note that the Symantec JIT using a handle-based object allocation system).
0206106A mov eax,0F97E78h
0206106F call 01F6B210 ; allocate space for
; Singleton, return result in eax
02061074 mov dword ptr [ebp],eax ; EBP is &singletons[i].reference
; store the unconstructed object here.
02061077 mov ecx,dword ptr [eax] ; dereference the handle to
; get the raw pointer
02061079 mov dword ptr [ecx],100h ; Next 4 lines are
0206107F mov dword ptr [ecx+4],200h ; Singleton's inlined constructor
02061086 mov dword ptr [ecx+8],400h
0206108D mov dword ptr [ecx+0Ch],0F84030h
As you can see, the assignment to singletons[i].reference is performed before the constructor for Singleton is called. This is completely legal under the existing Java memory model, and also legal in C and C++ (since neither of them have a memory model).
http://www.cs.umd.edu/~pugh/java/memoryModel/DoubleCheckedLocking.html
Apart from that
- It can break if the class is `Serializable`
- It can break if its 'Clonable`
- You can break by `Reflection` (I believe)
- it can break ff multiple classloaders are loaded the class
*How do you solve rule breakers?
- It is much safer to do eager initialization
- To prevent deserializing to create new object you may override `readResolve()` method in your class and throw exception
- To prevent cloning, you may overrride `clone()` and throw `CloneNotSupported` exception
- To escape for reflective instantion, we can add check in the constructor and throw exception.
Example
public class Singleton {
private static final Singleton INSTANCE = new Singleton();
private Singleton() {
// Check if we already have an instance
if (INSTANCE != null) {
throw new IllegalStateException("Singleton" +
" instance already created.");
}
}
public static final Singleton getInstance() {
return INSTANCE;
}
private Object readResolve() throws ObjectStreamException {
return INSTANCE;
}
private Object writeReplace() throws ObjectStreamException {
return INSTANCE;
}
public Object clone() throws CloneNotSupportedException {
// return INSTANCE
throw new CloneNotSupportedException();
}
}
After all I would suggest to use Enum as the safest way for Singleton (Since java5 the best way to do it is to use an enum)
public static enum SingletonFactory {
INSTANCE;
public static SingletonFactory getInstance() {
return INSTANCE;
}
}
Problem
What are the different ways we can break a singleton pattern in Java. I know one way i.e. if we do not synchronize the method in singleton , then we can create more than an instance of the class. So synchronization is applied. Is there a way to break singleton java class. ``` public class Singleton { private static Singleton singleInstance; private Singleton() { } public static Singleton getSingleInstance() { if (singleInstance == null) { synchronized (Singleton.class) { if (singleInstance == null) { singleInstance = new Singleton(); } } } return singleInstance; } } ```