Saturday, June 17, 2017

Singleton vs Reflection, Serialization and Cloning


Singleton:- only one instance of a class is created in JVM - lazy/early loading mechanism.
used to provide global point of access to the object.
used in logging, caches, thread pools, configuration settings etc.

In the multi-threading environment to prevent each thread to create another instance of singleton object and thus creating concurrency issue we will need to use locking mechanism.

This can be achieved by synchronized keyword. By using this synchronized keyword we prevent Thread2 or Thread3 to access the singleton instance while Thread1 inside the method getInstance().

Enum is thread safe and implementation of Singleton through Enum ensures that your singleton will have only one instance even in a multi-threaded environment.

public class SingletonClass {

    // static member
    private static SingletonClass singletonInstance;

    // private constructor
    private SingletonClass() {
    }

    // global point of access
    public static synchronized SingletonClass getInstance(){
        if(singletonInstance == null){
            singletonInstance=new SingletonClass();
            System.out.println("Created");
        }
        return singletonInstance;
    }
}


public enum SingletonEnum {
    INSTANCE;
    public void doPrint(){
        System.out.println("Singleton using Enum");
    }
}


public class SingletonTest {

    public static void main(String[] args) {
        System.out.println(SingletonClass.getInstance());
        System.out.println(SingletonClass.getInstance());
        SingletonEnum.INSTANCE.doPrint();
    }
}

How to prevent Singleton Pattern from Reflection, Serialization and Cloning?
There are mainly 3 concepts which can break singleton property of a singleton class.

Reflection:- Reflection allows instantiation of new objects, invocation of methods, and get/set operations on class variables dynamically at run time without having prior knowledge of its implementation.

// Singleton class
class Singleton
{
    // 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[] args)
    {
        Singleton instance1 = Singleton.instance;
        Singleton instance2 = null;
        try
        {
            Constructor[] constructors = Singleton.class.getDeclaredConstructors();
            for (Constructor constructor : constructors)
            {
                // Below code will destroy the singleton pattern
                constructor.setAccessible(true);
                instance2 = (Singleton) constructor.newInstance();
                break;
            }
        }
    
        catch (Exception e)
        {
            e.printStackTrace();
        }
        
    System.out.println("instance1.hashCode():- " + instance1.hashCode());
    System.out.println("instance2.hashCode():- " + instance2.hashCode());
    }
}


After running this class, you will see that hashCodes are different that means, 2 objects of same class are created and singleton pattern has been destroyed.

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

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


As enums don’t have any constructor so it is not possible for Reflection to utilize it. Enums have their by-default constructor, we can’t invoke them by ourself. JVM handles the creation and invocation of enum constructors internally. As enums don’t give their constructor definition to the program, it is not possible for us to access them by Reflection also. Hence, reflection can’t break singleton property in case of enums. 

Serialization:- Serialization is used to convert an object of byte stream and save in a file or send over a network. Suppose you serialize an object of a singleton class. Then if you de-serialize that object it will create a new instance and hence break the singleton pattern.

class Singleton implements Serializable
{
    // 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[] args)
    {
        try
        {
            Singleton instance1 = Singleton.instance;
            ObjectOutput out = new ObjectOutputStream(new FileOutputStream("file.text"));
            out.writeObject(instance1);
            out.close();
    
            // deserailize from file to object
            ObjectInput in = new ObjectInputStream(new FileInputStream("file.text"));
            
            Singleton instance2 = (Singleton) in.readObject();
            in.close();
    
            System.out.println("instance1 hashCode:- " + instance1.hashCode());
            System.out.println("instance2 hashCode:- " + instance2.hashCode());
        }
        
        catch (Exception e)
        {
            e.printStackTrace();
        }
    }
}


hashCode() of both instances is different, hence there are 2 objects of a singleton class. Thus, the class is no more singleton.

Overcome serialization issue:- To overcome this issue, we have to implement method readResolve() method.


class Singleton implements Serializable
{
    // public instance initialized when loading the class
    public static Singleton instance = new Singleton();
    
    private Singleton()
    {
        // private constructor
    }
    
    // implement readResolve method
    protected Object readResolve()
    {
        return instance;
    }
}


The readResolve method is called when ObjectInputStream has read an object from the stream and is preparing to return it to the caller. ObjectInputStream checks whether the class of the object defines the readResolve method. If the method is defined, the readResolve method is called to allow the object in the stream to designate the object to be returned. The object returned should be of a type that is compatible with all uses. If it is not compatible, a ClassCastException will be thrown when the type mismatch is discovered.

Cloning:- It is a concept to create duplicate objects. Using clone we can create copy of object. Suppose, we create clone of a singleton object, then it will create a copy that is there are two instances of a singleton class, hence the class is no more singleton.

class SuperClass implements Cloneable
{
  int i = 10;

  @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[] args) throws CloneNotSupportedException
  {
    Singleton instance1 = Singleton.instance;
    Singleton instance2 = (Singleton) instance1.clone();
    System.out.println("instance1 hashCode:- " + instance1.hashCode());
    System.out.println("instance2 hashCode:- " + instance2.hashCode());
  }
}


Two different hashCode means there are 2 different objects of singleton class.

Overcome Cloning issue:- To overcome this issue, override clone() method and throw an exception from clone method that is CloneNotSupportedException. Now whenever user will try to create clone of singleton object, it will throw exception and hence our class remains singleton.


// 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();
  }
}


Now we have stopped user to create clone of singleton class. If you don;t want to throw exception you can also return the same instance from clone method.

 @Override
  protected Object clone() throws CloneNotSupportedException
  {
    return instance;
  } 

Wednesday, June 14, 2017

Serialization/Deserialization

Serialization
process of conversion of one object state to another object state so that the object can be easily stored(file/memory/db) or transmitted(network).

Deserialization
process of reconstruction of object from a series of bytes according to the serialization format. i.e creating a semantically identical clone/replica of the original object.

This process of serializing an object is also called marshalling an object.
This process of deserializing an object is also called unmarshalling an object.

Note:- what gets serialized is the "value" of the object, or the contents, and not the class definition. Thus methods are not serialized.

What is serialVersionUID?
Each time an object is serialized, the object is stamped with a version ID number for that object's class.This ID number is called serialVersionUID and it is computed based on information about the class structure(based on the fields/methods that are defined in the class).
If you do not explicitly declare a serialVersionUID, JVM will do it for you automatically. This serialVersionUID is used for version control of object.

Why use serialVersionUID?
This number is used during deserialization to verify that the sender and receiver of a serialized object have loaded classes for that object that are compatible with respect to serialization. If the receiver has loaded a class for the object that has a different serialVersionUID than that of the corresponding sender's class, then deserialization will result in an InvalidClassException.

Example:- Suppose you made an Employee class and it has version id #333 (assigned by JVM),Now when you will serialize the object of that class (Suppose Employee object), JVM will assign UID to it as #333.

Consider a situation - in the future you need to edit or change your class and in that case when you modify it, JVM will assign it a new UID (Suppose #444). Now when you try to deserialize the employee object, JVM will compare serialized object's (Employee object) version ID(#333) with that of the class i.e #444(Since it was changed). On comparison JVM will find both version UID are different and hence Deserialization will fail. Hence if serialVersionUID for each class is defined by programmer itself. It will be same even if the class is evolved in future and hence JVM will always find that class is compatible with serialized object even though the class is changed.

Related Exception:-
java.io.NotSerializableException
java.io.InvalidClassException
   

Web Development

Design Phase:- Below all these represent different stages of the UX/UI design flow:- Wireframes represent a very basic & visual repr...