Thursday, November 7, 2019

Java Object Life Cycle

Object Life Cycle:




The heap is divided into two generations, young and tenured. Young consists of Eden, two Survivor spaces, and a Virtual space. Most of the objects that are created are initially allocated in Eden. After that, live objects are moved to a single Survivor space, while the other one is cleared of objects that became garbage. After that process is finished, the Survivor spaces are swapped, with all live objects copied from one to another and garbage cleaned. This process is called minor collection. After some cycles of minor collection, still living objects are moved into tenured generation. Eventually, the tenured generation is filled up and also needs to be cleaned. The process of garbage collection in the entire heap, including the tenured generation is called major collection, and happens less often than minor collections.
Now, we understand how the garbage collection is organized, but how to efficiently determine if an object is a live object or not?
In order to do so, GC builds several object trees with roots of the trees being objects that can be reached from the application. 

Examples of such objects are:


  • Local variables in the stack of the thread.
  • Active Java threads
  • Static variables.

So after building object trees the GC will have the objects divided into reachable, and, therefore, live objects, and non-reachable objects, or garbage.




Now it should be clearer why resource leaks are very dangerous - imagine a socket or a JDBC connection that has not been properly closed - the garbage collector will find it to be reachable and not collect it, taking away resources from your application.
So, let’s move on to the actual object lifecycle in Java.



1.    Created - memory was allocated, object placed in Eden;
2.    Initialized - object is initialized with a value and becomes ready to be used;
3.    In use - object is used for some period of time, until no references to it remain;
4.    Unreachable - after there are no references to the object it enters this state, and can            be collected by the GC;
5.    Finalized - object is garbage collected and memory it occupied is freed up.
        But that is not the most fine-grained view one can take. There exist several types of              references in java.lang.ref package and they differ in how GC treats them.

·         Strong reference - that is what is generally just named reference, meaning that some other object has a reference to it.

·         Soft reference - the GC will try to preserve object with only soft references to it as long as possible, but the object will be garbage collected if there is imminent danger of an OutOfMemory error.

·         Weak reference - this is weaker than soft reference, as the GC will collect this object at any time. Typically used for storing object reference is such a way so it will still be collected if all other references disappear.

·         Phantom reference - this reference also does not save an object from garbage collection, but adds an option to “access” object state after it has already been collected.

The improved diagram with different reference types.

Turns out, object lifecycle is not as simple as it is generally regarded in Java. While this answer still does not reflect many finer aspects of working with GC and object lifecycle, I hope it provides a good overview of how to think about memory allocation in Java.




Memory Allocation for Java object:

Memory Allocation for the object:

In Java, all objects are created on heap. Java uses the new operator to allocate memory for an object on heap. An array’s length is not a part of its class definition. It is defined at runtime. It is stored in the object header. You will not find the length instance variable in the array’s class definition when you perform introspection on an array’s class.
Java does not provide any direct means to compute the size of an object. You should not write a Java program that depends on the size of the objects anyway. The size of primitive types, for example, int, long, double, etc. is fixed for all JVM implementations. The layout and size of an object depends on the JVM implementation. Therefore, any code that depends on the size of objects may work on one platform and not on others

     Let’s See:

In Java, programmers deal with objects. The memory required for an object is always allocated on the heap. The memory is allocated implicitly using the new operator. For example you have a class called Student. You create an object of the Student class.

     Student s1= new Student();




Depending on the definition of the Student class, the Java runtime computes how much memory is needed, allocates the needed memory on heap, and stores the reference to that memory block in the comp reference variable. Note that when you want to create an Student object, you do not specify how much memory you need.

The new Student() part of the above statement indicates to Java that you want to create an object of the Student class. Java queries the definition of the Student class to compute the memory required to represent an Student object.

How it works?

Every Java object in memory has two areas: a header area and a data area.

1.   Header Area: It stores bookkeeping information to be used by the Java runtime, for example, the pointer to the object class, information about the garbage collection status of the object, locking information about the object, length of an array if the object is an array, etc.

2.   Data Area: It is used to store the values for all instance variables of the object. The header area layout is fixed for a particular JVM implementation whereas the data area layout is dependent on the object type.

Let’s see layout of an object in Java

The Java Hotspot virtual machine uses two machine-words (in 32-bit architecture one word is 4 bytes) for the object header.

If the object is an array, it uses three machine-words for its header. One extra word in the header is used to store the array length. However, most JVMs use three-machine words for an object header.


                              
                               The layout of an object in the Java Hotspot VM

The Java Hotspot VM uses a variable length object header to save memory on the heap. Since most Java objects are small, one machine-word savings per object for non-array objects is a significant heap space savings. The Java Hotspot VM’s object header contains the following information:
·   
Explanation of classptr:

This is the first machine-word in the object layout. It contains a pointer to the class information of the object. The class information includes the object’s method table, the object’s size, and a pointer to a class structure, which contains information about the class of the object, etc.

Explanation of  hash + age + lock:

This is the second machine-word in the object header. It contains the object’s hash code, age information, and lock fields. Age information is used in the process of reclaiming the object’s memory by the generational garbage collector. The generational garbage collector is a special type of garbage collector that uses the object’s age in its algorithm to reclaim an object’s memory.

Explanation of  arraylength:

This is the third machine-word in the object header. It is included only if the object is an array. It contains the length of the array. In this case, the object’s data area contains the array elements.


What is Java Object:

What is Java Object?

A Java object is a combination of data and procedures working on the available data. An object has a state and behavior. The state of an object is stored in fields (variables), while methods (functions) display the object's behavior. Objects are created from templates known as classes. 

An object has three main features

  • State: refers the data (value) of an object.
  • Behavior: refers the behavior (functionality) of an object such as playing cricket, dancing, etc.
  • Identity: An object identity is a unique ID. The value of the ID is not visible to the external user. However, it is used internally by the JVM to identify each object uniquely.
An object e.g., cow, car, table, TV, CD, DVD, etc. It can be physical or logical (tangible and intangible). The example of an intangible object is online reservation system.
                                                        
Note :

An object is a software bundle of variables and related methods.You can show real-world objects using software objects. If you want to represent real-world Cat as software objects in an animation program.
For example, an event is a common object used in GUI window systems to represent the action of a user pressing a F5 button for refresh on keyboard.



Methods of creating objects in Java

These are some ways in which you can create objects in Java:

     1)    By Using new Keyword : 

Using new keyword is the most basic way to create an object. This is the most common way to create an object in java.By using this method we can call any constructor.


public class NewKeyword 
{
    String name = "Amit Dhiman";
    public static void main(String[] args) 
    {
       
        NewKeyword obj = new NewKeyword();//creating object
        System.out.println(obj.name);
    }
}
Output:
Amit Dhiman


2)    By Using New Instance : 

We can create an object –Class.forName. We can use it to create the Object of a Class. Class. forName actually loads the Class in Java but doesn’t create any Object. To Create an Object of the Class you have to use the new Instance Method of the Class.


public class NewInstance
{
    String name = "Amit Dhiman";
    public static void main(String[] args)
    {
        try
        {
            Class cls = Class.forName("NewInstanceExample");
            NewInstanceExample obj =
                    (NewInstanceExample) cls.newInstance();
            System.out.println(obj.name);
        }
        catch (ClassNotFoundException e)
        {
            e.printStackTrace();
        }
        catch (InstantiationException e)
        {
            e.printStackTrace();
        }
        catch (IllegalAccessException e)
        {
            e.printStackTrace();
        }
    }
}
Output:
Amit Dhiman

     3)    Using clone() method: 

Whenever clone() is called on any object, the JVM actually creates a new object and copies all content of the previous object into it. Creating an object using the clone method does not invoke any constructor.
To use clone() method on an object we need to implement Cloneable and define the clone() method in it.


public class Clone implements Cloneable
{
    @Override
    protected Object clone() throws CloneNotSupportedException
    {
        return super.clone();
    }
    String name = "Amit Dhiman";

    public static void main(String[] args)
    {
        Clone obj1 = new Clone();
        try
        {
            Clone obj2 = (Clone) obj1.clone();
            System.out.println(obj2.name);
        }
        catch (CloneNotSupportedException e)
        {
            e.printStackTrace();
        }
    }
}
Output:
Amit Dhiman


Note :
·         Here we are creating the clone of an existing Object and not any new Object.
·         Class need to implement Cloneable Interface otherwise it will throw CloneNotSupportedException.

       4)    Using deserialization : 

Whenever we serialize and then deserialize an object, JVM creates a separate object. In deserialization, JVM doesn’t use any constructor to create the object.
To deserialize an object we need to implement the Serializable interface in the class.

Serializing an Object :


import java.io.*;

public class Deserialization implements Serializable
{
    private String name;
    Deserialization(String name)
    {
        this.name = name;
    }

    public static void main(String[] args)
    {
        try
        {
            Deserialization d =
                    new Deserialization("Amit Dhiman");
            FileOutputStream f = new FileOutputStream("file.txt");
            ObjectOutputStream oos = new ObjectOutputStream(f);
            oos.writeObject(d);
            oos.close();
            f.close();
        }
        catch (Exception e)
        {
            e.printStackTrace();
        }
    }
}
Object of DeserializationExample class is serialized using writeObject() method and written to file.txt file.

Deserialization of Object :


import java.io.*;

public class Deserialization
{
    public static void main(String[] args)
    {
        try
        {
            Deserialization d;
            FileInputStream f = new FileInputStream("file.txt");
            ObjectInputStream oos = new ObjectInputStream(f);
            d = (Deserialization)oos.readObject();
        }
        catch (Exception e)
        {
            e.printStackTrace();
        }
        System.out.println(d.name);
    }
}
Output:
Amit Dhiman

    5)    Using newInstance() method of Constructor class : 

This is similar to the newInstance() method of a class. There is one newInstance() method in the java.lang.reflect.Constructor class which we can use to create objects. It can also call parameterized constructor, and private constructor by using this newInstance() method.
Both newInstance() methods are known as reflective ways to create objects. In fact newInstance() method of Class internally uses newInstance() method of Constructor class.


import java.lang.reflect.*;

public class Reflection
{
    private String name;
    Reflection()
    {
    }
    public void setName(String name)
    {
        this.name = name;
    }
    public static void main(String[] args)
    {
        try
        {
            Constructor<Reflection> constructor
                = Reflection.class.getDeclaredConstructor();
            Reflection r = constructor.newInstance();
            r.setName("Amit Dhiman");
            System.out.println(r.name);
        }
        catch (Exception e)
        {
            e.printStackTrace();
        }
    }
}
Output:
Amit Dhiman