The singleton design pattern's intent is succinctly described by the seminal work of Gamma et al. \[[Gamma 95|AA. Java References#Gamma 95]\]:
{quote}
Ensure a class only has one instance, and provide a global point of access to it.
{quote}
"Since there is only one Singleton instance, any instance fields of a Singleton will occur only once per class, just like {{static}} fields. Singletons often control access to resources such as database connections or sockets." \[[Fox 01|AA. Java References#Fox 01]\]. Other applications of singletons involve maintaining performance statistics, system monitoring and logging, implementing printer spoolers or as simple as ensuring that only one audio file plays at a time. Classes that contain only {{static}} methods are good candidates for singletons.
Typically, the Singleton pattern uses a single instance of a class that encloses a {{private static}} class field. The instance can be created using _lazy initialization_, which means that the instance is not created when the class loads but when it is first used.
h2. Noncompliant Code Example (nonprivatenon-private constructor)
This noncompliant code example uses a non-private constructor for instantiating a singleton.
{code:bgColor=#FFcccc}
class MySingleton {
private static MySingleton INSTANCE;
protected MySingleton() {
// private constructor prevents instantiation by untrusted callers
INSTANCE = new MySingleton();
}
public static synchronized MySingleton getInstance() {
return INSTANCE;
}
}
{code}
A malicious subclass may extend the accessibility of the constructor from {{protected}} to {{public}}, allowing untrusted code to create multiple instances of the singleton. Also, the class field {{INSTANCE}} has not been declared as {{final}}.
h2. Compliant Solution ({{private}} constructor)
This compliant solution reduces the accessibility of the constructor to {{private}} and initializes the field {{INSTANCE}} immediately, allowing it to be declared {{final}}.
{code:bgColor=#ccccff}
class MySingleton {
private static final MySingleton INSTANCE = new MySingleton();
private MySingleton() {
// private constructor prevents instantiation by untrusted callers
}
public static synchronized MySingleton getInstance() {
return INSTANCE;
}
}
{code}
The {{MySingleton}} class need not be declared as final because it has a private constructor.
h2. Noncompliant Code Example (visibility across threads)
When the getter method is called by two (or more) threads simultaneously, multiple instances of the {{Singleton}} class might result if access is not synchronized.
{code:bgColor=#FFcccc}
class MySingleton {
private static MySingleton INSTANCE;
private MySingleton() {
// private constructor prevents instantiation by untrusted callers
}
// Lazy initialization
public static MySingleton getInstance() { // Not synchronized
if (INSTANCE == null) {
INSTANCE = new MySingleton();
}
return INSTANCE;
}
}
{code}
h2. Noncompliant Code Example (inappropriate synchronization)
Multiple instances can be created even if the singleton construction is encapsulated in a {{synchronized}} block.
{code:bgColor=#FFcccc}
public static MySingleton getInstance() {
if (INSTANCE == null) {
synchronized (MySingleton.class) {
INSTANCE = new MySingleton();
}
}
return INSTANCE;
}
{code}
This is because two or more threads may simultaneously see the field {{INSTANCE}} as {{null}} in the {{if}} condition, and enter the synchronized block one at a time.
h2. Compliant Solution (1) ({{synchronized}} method)
To avoid the issue of multiple threads creating more than one instance of the singleton, make {{getInstance()}} a {{synchronized}} method.
{code:bgColor=#ccccff}
class MySingleton {
private static MySingleton INSTANCE;
private MySingleton() {
// private constructor prevents instantiation by untrusted callers
}
// Lazy initialization
public static synchronized MySingleton getInstance() {
if (INSTANCE == null) {
INSTANCE = new MySingleton();
}
return INSTANCE;
}
}
{code}
h2. Compliant Solution (2) (double-checked locking)
Another compliant solution for implementing thread-safe singletons is the double-checked locking idiom.
{code:bgColor=#ccccff}
class MySingleton {
private static volatile MySingleton INSTANCE;
private MySingleton() {
// private constructor prevents instantiation by untrusted callers
}
// Double-checked locking
public static MySingleton getInstance() {
if (INSTANCE == null) {
synchronized (MySingleton.class) {
if (INSTANCE == null) {
INSTANCE = new MySingleton();
}
}
}
return INSTANCE;
}
}
{code}
This design pattern is often implemented incorrectly. Refer to [CON22-J. Do not use incorrect forms of the double-checked locking idiom] for more details on the double-checked locking idiom.
h2. Compliant Solution (3) (initialize-on-demand holder class idiom)
This compliant solution uses a {{static}} inner class to create the singleton instance.
{code:bgColor=#ccccff}
class MySingleton {
static class SingletonHolder {
static MySingleton INSTANCE = new MySingleton();
}
public static MySingleton getInstance() {
return SingletonHolder.INSTANCE;
}
}
{code}
This is known as the initialize-on-demand holder class idiom. Refer to [CON22-J. Do not use incorrect forms of the double-checked locking idiom] for more information.
h2. Noncompliant Code Example (Serializable singleton)
This noncompliant code example implements the {{java.io.Serializable}} interface which allows the class to be serializable. Deserialization of the class implies that multiple instances of the singleton can be created.
{code:bgColor=#FFcccc}
class MySingleton implements Serializable {
private static final long serialVersionUID = 6825273283542226860L;
private static MySingleton INSTANCE;
private MySingleton() {
// private constructor prevents instantiation by untrusted callers
}
// Lazy initialization
public static synchronized MySingleton getInstance() {
if (INSTANCE == null) {
INSTANCE = new MySingleton();
}
return INSTANCE;
}
}
{code}
A singleton's constructor cannot install any checks to enforce the requirement that the number of instances be limited to one because serialization provides a mechanism to bypass the object's constructor.
h2. Noncompliant Code Example ({{readResolve()}} method)
It is insufficient to add a {{readResolve()}} method that returns the original instance, to ensure the singleton property. This is insecure even if all the fields are declared {{transient}} or {{static}}.
{code:bgColor=#FFcccc}
class MySingleton implements Serializable {
private static final long serialVersionUID = 6825273283542226860L;
private static MySingleton INSTANCE;
private MySingleton() {
// private constructor prevents instantiation by untrusted callers
}
// Lazy initialization
public static synchronized MySingleton getInstance() {
if (INSTANCE == null) {
INSTANCE = new MySingleton();
}
return INSTANCE;
}
private Object readResolve() {
return INSTANCE;
}
}
{code}
At runtime, an attacker can add a class that reads in a crafted serialized stream:
{code}
public class Untrusted implements Serializable {
public static MySingleton captured;
public MySingleton capture;
public Untrusted(MySingleton capture) {
this.capture = capture;
}
private void readObject(java.io.ObjectInputStream in) throws Exception {
in.defaultReadObject();
captured = capture;
}
}
{code}
The crafted stream an be generated by serializing the following class:
{code}
public final class MySingleton implements java.io.Serializable {
private static final long serialVersionUID = 6825273283542226860L;
public Untrusted untrusted = new Untrusted(this); // Additional serial field
public MySingleton() { }
}
{code}
Upon deserialization, the field {{MySingleton.untrusted}} is reconstructed before {{MySingleton.readResolve()}} is called. Consequently, {{Untrusted.captured}} is assigned the deserialized instance of the crafted stream instead of {{MySingleton.INSTANCE}}. This issue is pernicious when an attacker can add classes to exploit the singleton guarantee of an existing serializable class.
h2. Compliant Solution ({{enum}} types)
It is recommended that stateful singleton classes be made non-serializable. As a precautionary measure, classes that are serializable must never save a reference to a singleton object in their non-transient or non-static instance variables. This prevents the singleton from being indirectly serialized.
Bloch \[[Bloch 08|AA. Java References#Bloch 08]\] suggests the use of an {{enum}} type as a replacement for traditional implementations when serializable singletons are indispensable.
{code:bgColor=#ccccff}
public enum MySingleton {
INSTANCE;
// Other methods
}
{code}
Functionally, this approach is equivalent to commonplace implementations and is safer. It ensures that only one instance of the object exists at any instant and also provides the serialization property as {{java.lang.Enum<E>}} extends {{java.io.Serializable}}.
h2. Noncompliant Code Example (non-transient instance fields)
This serializable noncompliant code example uses a non-transient instance field {{str}}.
{code:bgColor=#FFcccc}
class MySingleton implements Serializable {
private static final long serialVersionUID = 2787342337386756967L;
private static MySingleton INSTANCE;
private String[] str = {"one", "two", "three"}; // non-transient instance field
private MySingleton() {
// private constructor prevents instantiation by untrusted callers
}
public void displayStr() {
System.out.println(Arrays.toString(str));
}
private Object readResolve() {
return INSTANCE;
}
}
{code}
"If a singleton contains a nontransient object reference field, the contents of this field will be deserialized before the singletonâs {{readResolve}} method is run. This allows a carefully crafted stream to "steal" a reference to the originally deserialized singleton at the time the contents of the object reference field are deserialized." \[[Bloch 08|AA. Java References#Bloch 08]\].
h2. Noncompliant Code Example (transient fields)
This noncompliant code example declares the {{str}} instance field as {{transient}} so that it is not serialized.
{code:bgColor=#FFcccc}
class MySingleton implements Serializable {
// ...
private transient String[] str = {"one", "two", "three"}; // non-transient field
// ...
}
{code}
However, this is still insecure because of reasons described in the noncompliant code example ({{readResolve()}} method).
h2. Compliant Solution ({{enum}} types, non-transient fields)
This compliant solution uses the {{enum}} type to ensure that only one instance of the singleton exists at any time.
{code:bgColor=#ccccff}
public enum MySingleton {
INSTANCE;
private String[] str = {"one", "two", "three"}; // non-transient field
public void displayStr() {
System.out.println(Arrays.toString(str));
}
}
{code}
h2. Noncompliant Code Example (Cloneable singleton)
It is also possible to create a copy of the singleton by cloning it using the object's {{clone()}} method if the singleton class implements {{java.lang.Cloneable}} directly or through inheritance. This noncompliant code example shows a singleton that implements the {{java.lang.Cloneable}} interface.
{code:bgColor=#FFcccc}
class MySingleton implements Cloneable {
private static MySingleton INSTANCE;
private MySingleton() {
// private constructor prevents instantiation by untrusted callers
}
// Lazy initialization
public static synchronized MySingleton getInstance() {
if (INSTANCE == null) {
INSTANCE = new MySingleton();
}
return INSTANCE;
}
}
{code}
h2. Compliant Solution (override {{clone()}} method)
Avoid making the singleton class cloneable by not implementing the {{Cloneable}} interface or not deriving from a class that already implements it.
If the singleton class indirectly implements the {{Cloneable}} interface through inheritance, override the object's {{clone()}} method and throw a {{CloneNotSupportedException}} exception from within it \[[Daconta 03|AA. Java References#Daconta 03]\].
{code:bgColor=#ccccff}
class MySingleton implements Cloneable {
private static MySingleton INSTANCE;
private MySingleton() {
// private constructor prevents instantiation by untrusted callers
}
// Lazy initialization
public static synchronized MySingleton getInstance() {
if (INSTANCE == null) {
INSTANCE = new MySingleton();
}
return INSTANCE;
}
public Object clone() throws CloneNotSupportedException {
throw new CloneNotSupportedException();
}
}
{code}
See [MSC05-J. Make sensitive classes noncloneable] for more details about restricting misuse of the {{clone()}} method.
h2. Noncompliant Code Example (garbage collection)
When the utility of a class is over, it is free to be garbage collected. This behavior can be troublesome when the program needs to maintain only one instance throughout its lifetime.
A {{static}} singleton is garbage collected when its class loader becomes eligible for garbage collection. This usually happens when a nonstandard (custom) class loader is used to load the singleton. This noncompliant code example prints different values of the hashcode of the singleton object from different scopes.
{code:bgColor=#FFcccc}
{
ClassLoader cl1 = new MyClassLoader();
Class class1 = cl1.loadClass(MySingleton.class.getName());
Method classMethod = class1.getDeclaredMethod("getInstance", new Class[] { });
Object singleton = classMethod.invoke(null, new Object[] { });
System.out.println(singleton.hashCode());
}
ClassLoader cl1 = new MyClassLoader();
Class class1 = cl1.loadClass(MySingleton.class.getName());
Method classMethod = class1.getDeclaredMethod("getInstance", new Class[] { });
Object singleton = classMethod.invoke(null, new Object[] { } );
System.out.println(singleton.hashCode());
{code}
{mc}
back-up code
{
ClassLoader cl1 = new FirstClassLoader();
Class class1 = cl1.loadClass(MySingleton.class.getName());
Method instanceMethod = class1.getDeclaredMethod("getInstance", new Class[] { });
Object singleton = instanceMethod.invoke(null, new Object[] { } );
}
ClassLoader cl2 = new SecondClassLoader();
Class class2 = cl2.loadClass(MySingleton.class.getName());
Method instanceMethod = class2.getDeclaredMethod("getInstance", new Class[] { });
Object singleton = instanceMethod.invoke(null, new Object[] { } );
{mc}
Code that is outside the scope can create another instance of the singleton class though the requirement was to use only the original instance.
{mc}
// The following class produces the same hashcode from different scopes, so is safe
public class StaticClass {
public void doSomething() {
{
MySingleton ms = new MySingleton();
Object singleton = ms.getInstance();
System.out.println(singleton.hashCode());
}
MySingleton ms = new MySingleton();
Object singleton = ms.getInstance();
System.out.println(singleton.hashCode());
}
public static void main(String[] args) {
StaticClass sc = new StaticClass();
sc.doSomething();
}
}
{mc}
h2. Compliant Solution (prevent garbage collection)
This compliant solution takes into account the garbage collection issue described above. A class is not garbage collected until the {{ClassLoader}} object used to load it becomes eligible for garbage collection. An easier scheme to prevent the garbage collection is to ensure that there is a direct or indirect reference from a live thread to the singleton object that needs to be preserved.
This compliant solution demonstrates this technique and prints a consistent hashcode across all scopes. It uses the {{ObjectPreserver}} class based on \[[Patterns 02|AA. Java References#Patterns 02]\] and described in [CON03-J. Do not use background threads during class initialization].
{code:bgColor=#ccccff}
{
ClassLoader cl1 = new MyClassLoader();
Class class1 = cl1.loadClass(MySingleton.class.getName());
Method classMethod = class1.getDeclaredMethod("getInstance", new Class[] { });
Object singleton = classMethod.invoke(null, new Object[] { });
ObjectPreserver.preserveObject(singleton); // Preserve the object
System.out.println(singleton.hashCode());
}
ClassLoader cl1 = new MyClassLoader();
Class class1 = cl1.loadClass(MySingleton.class.getName());
Method classMethod = class1.getDeclaredMethod("getInstance", new Class[] { });
Object singleton = ObjectPreserver.getObject(); // Retrieve the preserved object
System.out.println(singleton.hashCode());
{code}
h2. Risk Assessment
Using improper forms of the singleton design pattern may lead to creation of multiple instances of the singleton and violate the expected contract of the class.
|| Rule || Severity || Likelihood || Remediation Cost || Priority || Level ||
| CON23- J | low | unlikely | medium | {color:green}{*}P2{*}{color} | {color:green}{*}L3{*}{color} |
h3. Automated Detection
TODO
h3. Related Vulnerabilities
Search for vulnerabilities resulting from the violation of this rule on the [CERT website|https://www.kb.cert.org/vulnotes/bymetric?searchview&query=FIELD+KEYWORDS+contains+CON32-J].
h2. References
\[[JLS 05|AA. Java References#JLS 05]\] [Chapter 17, Threads and Locks|http://java.sun.com/docs/books/jls/third_edition/html/memory.html]
\[[Fox 01|AA. Java References#Fox 01]\] [When is a Singleton not a Singleton?|http://java.sun.com/developer/technicalArticles/Programming/singletons/]
\[[Daconta 03|AA. Java References#Daconta 03]\] Item 15: Avoiding Singleton Pitfalls;
\[[Darwin 04|AA. Java References#Darwin 04]\] 9.10 Enforcing the Singleton Pattern
\[[Gamma 95|AA. Java References#Gamma 95]\] Singleton
\[[Patterns 02|AA. Java References#Patterns 02]\] Chapter 5, Creational Patterns, Singleton
\[[Bloch 08|AA. Java References#Bloch 08]\] Item 3: "Enforce the singleton property with a private constructor or an enum type" and Item 77: "For instance control, prefer enum types to readResolve"
\[[MITRE 09|AA. Java References#MITRE 09]\] [CWE ID 543|http://cwe.mitre.org/data/definitions/543.html] "Use of Singleton Pattern in a Non-thread-safe Manner"
----
[!The CERT Sun Microsystems Secure Coding Standard for Java^button_arrow_left.png!|CON22-J. Do not use incorrect forms of the double-checked locking idiom] [!The CERT Sun Microsystems Secure Coding Standard for Java^button_arrow_up.png!|11. Concurrency (CON)] [!The CERT Sun Microsystems Secure Coding Standard for Java^button_arrow_right.png!|VOID CON24-J. Use a unique channel to acquire locks on any file]
|