How to prevent Singleton Pattern from Reflection and Cloning

Posted By : Sudhir Kumar Ojha | 17-Dec-2018

In Object Oriented Programming (OOP), singleton design pattern allows you to create only one instance(Object) of class at a time. It is a part of creational design patterns. Here are the following important points about singleton pattern:

  1. Singleton classes can have only one instance i.e. one object per class and that instance should be globally accessible.
  2. java.lang.Runtime and java.awt.Desktop 2 singleton internal classes provided by JVM.
  3. Singleton class design pattern is a type of creational design pattern.
  4. We should take care of outer classes should be prevented to create an instance of a singleton class.

 

To create a singleton class:

  1. Make constructor of class as private.
  2. Create a static method that returns the return type object of the singleton class. The lazy initialization concept is used to achieve this.

 

Prerequisites

 

java 1.5 or later

Notepad or Notepad++ (Or any text editor you want)

or Eclipse IDE (Any version)

 

For example:

 

 package com.oodles.test;

class Singleton
{
   public static Singleton singleton = null;
   
   private Singleton()
   {
      // private constructor
   }
   
   public static Singleton getInstance()
   {
      if( singleton == null)
      {
         singleton = new Singleton();
      }
      return singleton;
   }
}
 

Now create class name Test to test that above implementation. In the following Test class, I have created two instances of Singleton class by using getInstance() method of Singleton class because getInstance() method is a static method hence we can call this method by using the class name. For example consider the following code snippet:  

 

 package com.oodles.test;
public class Test
{
   public static void main( String[] arguments)
   {
      Singleton singleton1 = Singleton.getInstance();
      Singleton singleton2 = Singleton.getInstance();
      System.out.println( "Hash code of singleton1 = "+ singleton1.hashCode() );
      System.out.println( "Hash code of singleton2 = "+ singleton2.hashCode() );
   }
}
 

Output:

 

But by using Reflection, and Cloning we can create multiple objects of the Singleton class. Consider the following:

1. Using Reflection:

 

 for ( Constructor constructor : constructors )
{
    // Below code will destroy the singleton pattern 
    constructor.setAccessible( true );
    instance1 = ( Singleton ) constructor.newInstance();// Here you will be able to create multiple instances.
    break;
}
 

Overcome reflection issue: To overcome reflection issue raised by reflection, enums are used because java ensures internally that enum value is instantiated only once. In Java, Enums are special types and globally accessible, they can be used for singletons. Its only disadvantage is that it is not flexible i.e it does not allow lazy initialization.

 

 //Java program for Enum type singleton 
public enum Test
{ 
  INSTANCE; 
} 
 

2. By using cloning:

By using cloning we can create multiple instances of that class. Using clone we can create a copy of the object. Consider the following example:

 

 package com.oodles.test;

class SuperClass implements Cloneable 
{ 
  @Override
  protected Object clone() throws CloneNotSupportedException  
  { 
    return super.clone(); 
  } 
} 
  
// Singleton class 
class Singleton extends SuperClass 
{ 
  // public instance initialized when loading the class 
  public static Singleton instance = new Singleton(); 
  
  private Singleton()  
  { 
    // private constructor 
  } 
}
public class Test
{
   public static void main( String[] arguments) throws CloneNotSupportedException
   {
      Singleton singleton1 = Singleton.instance; 
      Singleton singleton2 = (Singleton) singleton1.clone(); 
      System.out.println("Hash code of singleton1 = "
                             + singleton1.hashCode()); 
      System.out.println("Hash code of singleton1 = " 
                             + singleton2.hashCode()); 
   }
}
 

 

Output:

 

 There are two different hashCode that means two different objects of the singleton class.

 

 

Overcome clone issue: To overcome the object clone issue, just override the clone() method in Singleton class and throw CloneNotSupportedException. Whenever we try to use clone() method it will throw a CloneNotSupportedException, otherwise it is a perfect example of singleton class. Consider the following example

 

 package com.oodles.test;

class SuperClass implements Cloneable
{
   @Override
   protected Object clone() throws CloneNotSupportedException
   {
      return super.clone();
   }
}

// Singleton class 
class Singleton extends SuperClass
{
   // public instance initialized when loading the class 
   public static Singleton instance = new Singleton();

   private Singleton()
   {
      // private constructor 
   }

   @Override
   protected Object clone() throws CloneNotSupportedException
   {
      throw new CloneNotSupportedException();
   }
}

public class Test
{
   public static void main( String[] arguments) throws CloneNotSupportedException
   {
      Singleton singleton1 = Singleton.instance;
      Singleton singleton2 = ( Singleton ) singleton1.clone();
      System.out.println( "Hash code of singleton1 = " + singleton1.hashCode() );
      System.out.println( "Hash code of singleton1 = " + singleton2.hashCode() );
   }
}

 

Output:

 

 

Reference:

For more info please visit https://www.geeksforgeeks.org/prevent-singleton-pattern-reflection-serialization-cloning/ 

About Author

Author Image
Sudhir Kumar Ojha

Sudhir Kumar Ojha is having skills to work as Software developer & having good knowledge of Java.

Request for Proposal

Name is required

Comment is required

Sending message..