A Google Code project on detecting singletons in Java code has released its code under Apache Software License. This tool is useful for detecting singletons based on their usage pattern and these patterns are classified as {S, H, M, F}+ingleton. The author introduces these new terminologies based on whether the Singleton is implemented in a classic, helper, method, field based approach. The details of this can be learned from the project website. The output is written to a GraphML format which could be viewed using yEd. This provides a visual representation of singletons and their class references with in a library. This helps developers to fix the unwise way of using Singletons. Here is a sample graph generated from Google Singleton Detector (GSD) for DOM4J library.
GSD generated GraphML representation for DOM4J library
Singletons were once acclaimed the most used creational design patterns in Java. In the past few years, the usage has been mostly restricted by developers due to its lack of testability in the agile and test driven development world. GSD is at its early stage and has some known limitations. But, this is a good start and niche tool for Java developers to detect singletons in legacy projects and can re-factor if needed.
As defined by GoF in “Design Patterns: Elements of Reusable Object-Oriented Software“, the purpose of Singleton pattern is to ensure a class has only one instance, and provide a global point of access to it. Java has widely adopted this pattern since its inception. There are many arguments which discourage the use of Singletons in Java as they introduce global state which makes it difficult to test. Also, there are some known issues around double-checked locking pattern (DCLP) as there is no guarantee it will work on single or multi processor machines due to out of order writes implemented in JVM prior to 1.5. Double-checked locking idiom was used to avoid expensive synchronizations in the Singleton implementation. But, over time this idiom was proven to be ineffective due to its limitations until the memory model was revised in 1.5. So, the fallback option prior to 1.5 was to accept synchronization or use a static field. The classical singleton implementation in Java using static field is shown below.
public class Singleton {
private static Singleton _instance;
private Singleton() {
}
public static Singleton Instance() {
if (_instance == null)
_instance = new Singleton();
return _instance;
}
}
This design ensures that only one instance of Singleton object is ever created. The constructor is declared private and the Instance() method is declared static which creates only one object. This implementation holds good for a single-threaded program. However, when multiple threads are introduced, it is possible that Instance() method to return two different instances of the Singleton object. Synchronizing Instance() method would solve this issue at an extra performance overhead. But, it eliminates our threading issues. The above code is modified to support synchronization.
public class Singleton {
private static Singleton _instance;
private Singleton() {
}
public static Singleton Instance() {
if (_instance == null) {
synchronized (Singleton.class) {
_instance = new Singleton();
}
}
return _instance;
}
}
Even with this approach, it is not guaranteed that only one instance of Singleton object would be created because of the blocking nature of synchronization. Both the threads wait to acquire the lock on the object and end up creating two Singleton objects violating the purpose of the pattern. To circumvent this problem, double-checked locking idiom was introduced. The following code shows the double-checked locking implementation of Singleton pattern.
public class Singleton {
private static Singleton _instance;
private Singleton() {
}
public static Singleton Instance() {
if (_instance == null) {
synchronized (Singleton.class) {
if (_instance == null) {
_instance = new Singleton();
}
}
}
return _instance;
}
}
DCLP does not allow multiple threads to create multiple Singleton objects. Instead, they are not guaranteed to work on either single or multi-processor machines due to the out of order writes observed in various JVM implementations prior to 1.5. The most obvious reason is that the writes which initialize _instance and write to the _instance field can be reordered by the compiler or the cache, which would have the effect of returning partially constructed Singleton object. This would end up reading an uninitialized object, thus causing the problem in JVMs prior to 1.5.
Under the new memory model implemented as part of JSR 133 suggests making the _instance field volatile should solve the problem of DCLP. This is because the initialization of the Singleton object by the constructing thread happens-before the return of its value by the thread that reads it. This JSR refines the semantics of threads, locks, volatile variables, and final fields. This also proposes a replacement “Initialization On Demand Holder” for DCLP which is thread safe and simpler to use and avoids initialization issues.
private static class LazySingletonHolder {
public static Singleton _instance = new Singleton();
}
public static Singleton Instance() {
return LazySingletonHolder._instance;
}