Over a million developers have joined DZone.
{{announcement.body}}
{{announcement.title}}

Creational Design Pattern Series: Singleton Pattern

DZone's Guide to

Creational Design Pattern Series: Singleton Pattern

Design patterns often come with a lot of implementation concerns.

· Java Zone ·
Free Resource

Java-based (JDBC) data connectivity to SaaS, NoSQL, and Big Data. Download Now.

Every now and then, it’s important to have only one instance for a class. Usually, singletons are used for centralized management of resources and they provide a global point of access to themselves.

Some of the common examples where singleton pattern is used include logger classes, configuration classes, etc.

Though it seems to be a simple design pattern, when it comes to implementation, it comes with a lot of implementation concerns. Here, we are going to look at various ways of creating a Singleton class that fulfills its purpose:

Eager Initialization

Eager initialization is the simplest approach wherein the instance of the class is created at the time of class loading.

Let’s look at the example below.

public class EagerlyInitializedSingleton {

  /** private constructor to prevent others from instantiating this class */
  private EagerlyInitializedSingleton() {}

  /** Create an instance of the class at the time of class  loading */
 private static final EagerlyInitializedSingleton instance = new EagerlyInitializedSingleton();

  /** Provide a global point of access to the instance */
  public static EagerlyInitializedSingleton getInstance() {
      return instance;
  }

}


The drawback of this approach is that the instance is created irrespective of whether it is accessed or not. If this instance is not a big object and if you can live with it being unused, this is the best approach. But, it can have performance implications if it allocates a large number of system resources and remains unused.

Eagerly Initialized Singleton With Static Block

We can also create the instance of the class in a static block. This works because the static block is executed only once at the time of class loading.

The advantage of this approach is that we can write our initialization logic or handle exceptions in the static block.

Here is an example:

public class EagerlyInitializedStaticBlockSingleton {

    private static EagerlyInitializedStaticBlockSingleton instance;

    /** Don't let anyone else instantiate this class */
    private EagerlyInitializedStaticBlockSingleton() {}

    /** Create the instance in a static block */
    static {
        try {
            instance = new EagerlyInitializedStaticBlockSingleton();
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }

    /** Provide a public method to get the instance that is created */
    public static EagerlyInitializedStaticBlockSingleton getInstance() {
        return instance;
    }
}


Even this approach may lead to resource wastage. This is because the instance of a class is created always, whether it is required or not.

Let’s solve the above problem with the next approach.

Lazy Initialization

Lazy initialization delays the creation of an object, the calculation of a value, or some other expensive process until the first time it is accessed. In singleton pattern, it restricts the creation of instance until requested the first time.

Here is an example:

public class LazilyInitializedSingleton {

    private static LazilyInitializedSingleton instance;

    /** Don't let anyone else instantiate this class */
    private LazilyInitializedSingleton() {}

    /** Create the instance lazily when it is accessed for the first time */
    public static synchronized LazilyInitializedSingleton getInstance() {
        if(instance == null) {
            instance = new LazilyInitializedSingleton();
        }
        return instance;
    }

}


Note that the use of synchronized keyword in the getInstance() method prevents race condition in multi-threaded environments.

Let’s say that the instance is not created yet and two threads enter the getInstance() method simultaneously. In such a case, the null check will evaluate to true and both the threads will create a new instance of the same class.

The synchronized keyword ensures that only one thread can execute the getInstance() method at a time.

Lazily-Initialized, Double-Checked Locking

Although the synchronized keyword added to the getInstance() method prevents race conditions, it may incur some performance penalty.

In double-checked locking, instead of making the entire method synchronized, we create a synchronized block and wrap only the instantiation part inside the synchronized block.

public class LazilyInitializedDoubleCheckedLockingSingleton {

    private static volatile LazilyInitializedDoubleCheckedLockingSingleton instance;

    /** private constructor to prevent others from instantiating this class */
    private LazilyInitializedDoubleCheckedLockingSingleton() {}

    /** Initialize the singleton lazily in a synchronized block */
    public static LazilyInitializedDoubleCheckedLockingSingleton getInstance() {
        if(instance == null) {
            synchronized (LazilyInitializedDoubleCheckedLockingSingleton.class) {
                // double-check
                if(instance == null) {
                    instance = new LazilyInitializedDoubleCheckedLockingSingleton();
                }
            }
        }
        return instance;
    }
}


This approach helps us to recheck the instance variable again in the synchronized block. The double-checking is very important here. Let’s consider an example. When two threads T1 and T2 invokes the getInstance() method simultaneously, the instance==null check will evaluate to true, so both will enter the synchronized block one by one. If the double check was not there, both threads would create a new instance.

Bill Pugh Solution (Lazily-Initialized, Inner-Class Singleton)

Bill Pugh suggested a concept of inner static classes for the singleton. This is based on the Initialization-on-demand holder idiom. This idiom uses inner classes and does not use any synchronization constructs. It uses static blocks, but in a different way.

Out of all other approaches, this approach works well in single- and multi-threaded environments without a performance impact.

Let’s look at an example:

public class LazilyInitializedInnerClassSingleton {

    /** private constructor to prevent others from instantiating this class */
    private LazilyInitializedInnerClassSingleton() {}

    /** This inner class is loaded only after getInstance() is called for the first time. */
    private static class InnerSingletonInitializer {
        private static final LazilyInitializedInnerClassSingleton INSTANCE = new LazilyInitializedInnerClassSingleton();
    }

    public static LazilyInitializedInnerClassSingleton getInstance() {
        return InnerSingletonInitializer.INSTANCE;
    }
}


Here, the inner class is not loaded until the getInstance() method is invoked for the first time. This is the most widely used approach as it does not use synchronization.

Using Enum

Enum provides implicit support for thread safety and only one instance is guaranteed. This is also a good way to have singleton with minimum effort.

public enum EnumSingleton {

    INSTANCE;

    //other
}


To get the instance of this Enum, we need to call  EnumSingleton.INSTANCE. The obvious drawback is that we cannot have lazy loading in Enum.

We have seen various approaches to define Singleton so far. Let’s look at how to break singleton pattern.

Breaking Singleton Using Reflection

Using the Reflection API, we can change the access level of the constructor from private to public. We can then instantiate the class as many times as we need using this public constructor.

Here is an example:

public class Singleton {

    /** private constructor to prevent others from instantiating this class */
    private Singleton() {}

    /** Create an instance of the class at the time of class loading */
    private static Singleton instance = new Singleton();

    /** Provide a global point of access to the instance */
    public static Singleton getInstance() {
        return instance;
    }
}
public class ReflectionSingleton {

    public static void main(String[] args) {

        Singleton instance1 = Singleton.getInstance();

        Singleton instance2 = null;

        try {

            Constructor[] cstr = Singleton.class.getDeclaredConstructors();

            for (Constructor constructor: cstr) {

                //Setting constructor accessible

                constructor.setAccessible(true);

                instance2 = (Singleton) constructor.newInstance();

                break;

            }

        } catch (Exception e) {

            System.out.println(e);

        }

        System.out.println(instance1.hashCode());

        System.out.println(instance2.hashCode());

    }
}


The hash code for both the instances would be different.

Notice how we created a new instance of the Singleton using constructor.newInstance(). This destroys the singleton pattern.

How Do We Prevent This?

We can throw an exception from the private constructor if the instance is already created.

public class ProtectionAgainstReflectionSingleton {

    /** private constructor to prevent others from instantiating this class */
    private ProtectionAgainstReflectionSingleton() {
        // protect against instantiation via reflection
        if(instance != null) {
            throw new IllegalStateException("Singleton already initialized");
        }
    }

    /** Create an instance of the class at the time of class loading */
    private static final ProtectionAgainstReflectionSingleton instance = new ProtectionAgainstReflectionSingleton();

    /** Provide a global point of access to the instance */
    public static ProtectionAgainstReflectionSingleton getInstance() {
        return instance;
    }
}


However, we cannot use this technique with the lazy initialization approach.

Are you sure we don’t have any loopholes in the above example?

What if we change the access level of instance field from private to public and set it to null every time object gets created. This allows us to create as many objects as we want.

public class ReflectionWithPublicFieldSingleton {

    public static void main(String[] args) {
        Singleton instance1 = Singleton.getInstance();
        Singleton instance2 = null;

        try {
            Field instance = Singleton.class.getDeclaredField("instance");
            instance.setAccessible(true);
            instance.set(instance, null);

            Constructor[] cstr = Singleton.class.getDeclaredConstructors();

            for (Constructor constructor: cstr) {

                //Setting constructor accessible

                constructor.setAccessible(true);

                instance2 = (Singleton) constructor.newInstance();

                break;
            }
        } catch (Exception e) {
            System.out.println(e);
        }
        System.out.println(instance1.hashCode());
        System.out.println(instance2.hashCode());

    }
}


Here, the attacker can change the value of instance from not-null to null once the object is created.

We can prevent this by simply adding the final keyword to the instance field.

private static final Singleton instance = new Singleton();


The Reflection API cannot convert final to a non-final field. This approach again works only with eager initialization.

So far, we have seen how to implement singleton and how to protect when Reflection API is used. Now, let us see other problems that may arise.

Singleton and Serialization

Let’s say your application is distributed and it frequently serializes the objects in the file system, only to read them later when required.

Deserialization always creates a new instance. It does not matter if the constructor is private or not. There can be more than one instance of the same singleton class inside the JVM, violating the singleton property.

 Let’s understand using an example.

public class SerializableSingleton implements Serializable {

    private static final long serialVersionUID = -6265755052204900542L;

    private static SerializableSingleton instance;

    private SerializableSingleton() {}

    public static synchronized SerializableSingleton getInstance() {
        if(instance == null) {
            instance = new SerializableSingleton();
        }
        return instance;
    }
}


public class SerializationWithSingleton {

    public static void main(String[] args) {
        SerializableSingleton instance1 = SerializableSingleton.getInstance();

        try {
            // Serialize
            ObjectOutput out = new ObjectOutputStream(new FileOutputStream("singleton.serializable"));
            out.writeObject(instance1);
            out.close();

            // Deserialize
            ObjectInput in = new ObjectInputStream(new FileInputStream("singleton.serializable"));
            SerializableSingleton instance2 = (SerializableSingleton) in.readObject();
            in.close();

            System.out.println("instance1 hashCode: " + instance1.hashCode());
            System.out.println("instance2 hashCode: " + instance2.hashCode());
        } catch (IOException ex) {
            ex.printStackTrace();
        } catch (ClassNotFoundException ex) {
            ex.printStackTrace();
        }

    }
}


Here, instance1 and instance2 are two different instances having two different values as their field variables. This violates the singleton concept.

The solution is to implement the  readResolve method, which is invoked when creating the deserialized object before returning it to the caller.

public class SerializableWithReadResolveSingleton implements Serializable {
     private static final long serialVersionUID = 1911904003687931976L;

     private static SerializableWithReadResolveSingleton instance;

    private SerializableWithReadResolveSingleton() {}

    protected Object readResolve() {
        return instance;
    }

    public static synchronized SerializableWithReadResolveSingleton getInstance() {
        if(instance == null) {
            instance = new SerializableWithReadResolveSingleton();
        }
        return instance;
    }

}


public class SerializationWithReadResolveSingleton {

    public static void main(String[] args) {
        SerializableWithReadResolveSingleton instance1 = SerializableWithReadResolveSingleton.getInstance();

        try {
            // Serialize
            ObjectOutput out = new ObjectOutputStream(new FileOutputStream("singleton.serializable"));
            out.writeObject(instance1);
            out.close();

            // Deserialize
            ObjectInput in = new ObjectInputStream(new FileInputStream("singleton.serializable"));
            SerializableWithReadResolveSingleton instance2 = (SerializableWithReadResolveSingleton) in.readObject();
            in.close();

            System.out.println("instance1 hashCode: " + instance1.hashCode());
            System.out.println("instance2 hashCode: " + instance2.hashCode());
        } catch (IOException ex) {
            ex.printStackTrace();
        } catch (ClassNotFoundException ex) {
            ex.printStackTrace();
        }

    }
}


This code will produce the same hash code for both the instances. Now, the singleton property is preserved, and only one instance of the singleton class exists within the JVM.

Conclusion

In this article, we learned singleton design pattern and various ways to define singleton. We also learned the pros and cons of every approach. If you have any suggestions or queries, feel free to drop a comment.

We will look at the Factory Method pattern in the next post.

The complete source code can be found in my GitHub repository.

Connect any Java based application to your SaaS data.  Over 100+ Java-based data source connectors.

Topics:
java ,creational design patterns ,singleton ,software engineering

Published at DZone with permission of

Opinions expressed by DZone contributors are their own.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}