What are the different ways we can break a singleton pattern in Java
What are the different ways we can break a singleton pattern in Java
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; } }
Answer by Dylan Meeus for What are the different ways we can break a singleton pattern in Java
Multithreading is the biggest issue with singletons. You can avoid that by synchronizing or using eager initialisation.
Another way would be to use singleton where you're not supposed to. By using the singleton pattern you might apply it in a way that obstructs your program in later development. (E.G, creating a singleton "player" in a game, because you assume it's a singleplayer game. Next step in development "add co-op functionality").
The singleton pattern has it's advantages, but don't use it without carefull consideration.
Answer by Keerthivasan for What are the different ways we can break a singleton pattern in Java
AFAIK, there are two ways it could be broken
Using Reflection
When there are custom classloaders, more than one (i.e. parent class loader).all singletons should be loaded by common parent classloader.
Answer by skiwi for What are the different ways we can break a singleton pattern in Java
A note first: It would be better in this case, mainly for readability, to make the whole getSingleInstance() { }
synchronized
:
public synchronized static Singleton getSingleInstance() { if (singleInstance == null) { singleInstance = new Singleton(); } return singleInstance; }
Other than that, I don't think it is easy to break the code. Of course if you add recursive calls then it is possible to break it, like this:
- Call the constructor of some other class inside this
Singleton
's constructor. - In the constructor of that class, try to obtain this
Singleton
instance.
But that's the only thing I can think about, and you cannot protect yourself from that in the Singleton
class.
Answer by Satheesh Cheveri for What are the different ways we can break a singleton pattern in Java
Starting with your given code, "Double-Checked Locking" can be brocken at some enviroment, 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 throwCloneNotSupported
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; } }
Answer by Evgeniy Dorofeev for What are the different ways we can break a singleton pattern in Java
One way is Serialization. If you do not implement readResolve then reading a singleton with ObjectInputStream.readObject() will return a new instance of this singleton.
Answer by Sean Patrick Floyd for What are the different ways we can break a singleton pattern in Java
Actually a safe version without the need for synchronization is the version with a nested holder class:
public final class Singleton{ public static final Singleton getInstance(){ // no need for synchronization since the classloader guarantees to initialize // Holder.INSTANCE exactly once before handing out a reference to it return Holder.INSTANCE; } private Singleton(); private static class Holder{ private static final Singleton INSTANCE = new Singleton(); } }
Other safe versions are:
-
public final class Singleton{ public static final Singleton getInstance(){ return INSTANCE; } private Singleton(); private static final Singleton INSTANCE = new Singleton(); }
-
public enum Singleton{ INSTANCE; }
All of these versions have pros and cons, but none of them needs explicit synchronization since they all rely on the ClassLoader and its built-in Thread safety.
As the others have written, you can break some of these patterns through Deserialization. Read Effective Java by Joshua Bloch (Items 74 to 78) about preventing such attacks (the enum singleton pattern is safe against such attacks out of the box).
Answer by Tim B for What are the different ways we can break a singleton pattern in Java
The synchronized approach will work, but will also slow down every access to the singleton to protect something that only ever happens in the first access.
The simplest and safest way is just to do eager initialization, that is always safe as Java guarantees all member variables are set before it lets anyone access them.
public class Singleton { private static Singleton singleInstance = new Singleton(); private Singleton() { } public static Singleton getSingleInstance() { return singleInstance; } }
Your current approach is actually broken even with your synchronized loop - because double-check locking is broken. You need to mark the singleton variable as volatile
if you are going to use it for double-check locking since otherwise there are still ways for threads to access an incompletely-initialized object. See http://en.wikipedia.org/wiki/Double-checked_locking#Usage_in_Java for more details.
Answer by Kuldeep Singh for What are the different ways we can break a singleton pattern in Java
Suppose you have implemented Singleton class as "SingletonPattern" as below. package com.example.pattern;
public class SingletonPattern { private static SingletonPattern pattern; public static SingletonPattern getInstance() { if (pattern == null) { synchronized (SingletonPattern.class) { if (pattern == null) { pattern = new SingletonPattern(); } } } return pattern; } }
Now you can break you the Singleton behavior of this class by using following approach.
Class c = Class.forName("com.example.pattern.SingletonPattern"); System.out.println((SingltonPattern) c.newInstance());
Fatal error: Call to a member function getElementsByTagName() on a non-object in D:\XAMPP INSTALLASTION\xampp\htdocs\endunpratama9i\www-stackoverflow-info-proses.php on line 72
0 comments:
Post a Comment