Monday 1 April 2013

Understanding Strong, Soft, Weak and Phantom References



Understanding Strong, Soft, Weak and Phantom References.

In java, there are four types of references:-
  1. Strong Reference
  2. Soft Reference
  3. Weak Reference
  4. Phantom Reference
Strong Reference: - A strong reference is an ordinary Java reference, it is nothing but what we use in our programming every day. This is the default reference for objects. As long as there is a strong reference to an object, it cannot be garbage collected. For example:- 

ReferenceClass strongReference = new ReferenceClass();

Soft Reference: - Soft Reference is little bit stronger that weak reference. If plenty of memory is available then soft reference is not eligible for garbage collection. That is, it is eligible for garbage collection, but garbage collector can remove it based on the memory requirement. If less memory is left then it will collect the soft references. A soft reference is exactly like a weak reference, except that it is less eager to throw away the object to which it refers. This makes them (soft reference) an excellent candidate for implementing object cache's. For Example:-

ReferenceClass becameSoftReferenceObject = new ReferenceClass();

            SoftReference<ReferenceClass> softReference = new SoftReference<ReferenceClass>(becameSoftReferenceObject);


Weak Reference: - A weak reference, isn't strong enough to force an object to remain in memory. 


ReferenceClass becameWeakReferenceObject = new ReferenceClass();

WeakReference<ReferenceClass> weakReference = new WeakReference<ReferenceClass>(becameWeakReferenceObject);

Then somewhere in the code we can use weakReference.get() to get the actual ReferenceClass object. As weak reference isn't strong enough to prevent from garbage collection, so we will find (if there are no strong references to the ReferenceClass) that weakReference.get() will  return null. This we will also see in the below example.


Phantom Reference: - The main difference between a weak and a phantom reference is that the get method of a phantom reference will always return null.  It allows us to determine the exact moment of removing an object from memory. It can be needed in work with very big images, when it is required to clean complete image from memory, before another image starts loading, to prevent from OutOfMemoryError. The PhantomReference, however cleans up the object and enqueues the
reference object to a ReferenceQueue that a class can use for clean up. The object reference is appended to a ReferenceQueue and we can use this to clean up after a garbage collection.

ReferenceQueue referenceQueue = new ReferenceQueue();
PhantomReference<ReferenceClass> phantom = new PhantomReference(
                        phantomRefObject, referenceQueue);

When we construct a phantom reference we must always pass a ReferenceQueue object(as above). This indicates that we can use a phantom reference to see when our object is Garbage Collected. 


Reference queues

 The ReferenceQueue class makes it easy to keep track of dead references. If we pass a ReferenceQueue into a weak reference's constructor, the reference object will be automatically inserted into the reference queue when the object to which it pointed becomes garbage. We can process the ReferenceQueue and perform whatever cleanup is needed for dead references at some time of regular interval.

Note: - Using different types of Java references, allows reducing probability of memory leaks, as well as using memory more effectively.


Strong Reference Implementaion 

/* Strong references never get garbage collected, This is the default reference for objects.
 */
package com.gaurav.javareferences;

public class StrongRefernceExample {

    public static void GrabgecollectionCall() {
        try {
            System.out.println("Call for the garbage collection");
            System.gc();
            System.out.println("Thread is Sleeping now for 3S");
            Thread.sleep(3000);// for 3 seconds.
        } catch (InterruptedException ie) {
            ie.getMessage();
        }
    }

    public static void main(String args[]) {

        System.out.println("For the Creation of a strong references object");

        // This is example of a strong reference object.
        // If all the refernce of the below object is not available then the
        // object will get garbage collected.

        // @SuppressWarnings("unused")
        ReferenceClass strongReference = new ReferenceClass();

        // Attempt to claim a suggested reference.
        StrongRefernceExample.GrabgecollectionCall();

        System.out
                .println("Strong object refernce value before removing the refernces-"
                        + strongReference);
        // The object may now be collected.
        strongReference = null;

        StrongRefernceExample.GrabgecollectionCall();

        System.out
                .println("Strong object refernce value after removing the refernces-"
                        + strongReference);

        System.out.println("*****Execution Completed*****");

    }

    public static class ReferenceClass {
        protected void finalize() {
            System.out
                    .println("Calling the finalize method of ReferenceClass(a static inner class), Strong reference is now removed");
        }
    }

}


Soft Reference Implementaion

/*    Soft references only get collected if the JVM absolutely needs the memory.

 */
package com.gaurav.javareferences;

import java.lang.ref.SoftReference;
import java.util.ArrayList;
import java.util.List;

/*
 * This is a sample example for identifying and showing memory leaks in Java
 *
 */
public class SoftReferenceExample {

    public static void GrabgecollectionCall() {
        try {
            System.out.println("Call for the garbage collection");
            System.gc();
            System.out.println("Thread is Sleeping now for 3S");
            Thread.sleep(3000);// for 3 seconds.
        } catch (InterruptedException ie) {
            ie.getMessage();
        }
    }

    public static void main(String args[]) {

        System.out.println("For the Creation of a soft reference object");

        // This is now a soft reference.
        // The object will be collected only if no strong references exist and
        // the JVM really needs the memory.

        ReferenceClass becameSoftReferenceObject = new ReferenceClass();

        SoftReference<ReferenceClass> softReference = new SoftReference<ReferenceClass>(
                becameSoftReferenceObject);

        // Attempt to claim a suggested reference.
        SoftReferenceExample.GrabgecollectionCall();

        // Checking the memory reference of softReference object,before making
        // the becameSoftReferenceObject = null
        System.out
                .println("Checking the softReference object reference value before GC call-"
                        + softReference.get());

        // As here we are not removing the reference of
        // becameSoftReferenceObject, but due to Memory requirement
        // GrabgecollectionCall is done.
        becameSoftReferenceObject = null;
        SoftReferenceExample.GrabgecollectionCall();

        System.out
                .println("Consuming heap space by creating the large ArrayList object");
        try {
            // This will create a large objects list in the heap
            List<SoftReferenceExample> heapList = new ArrayList<SoftReferenceExample>(
                    10000);
            while (true) {
                heapList.add(new SoftReferenceExample());
            }
        } catch (OutOfMemoryError e) {
            // The soft object should have been collected before this
            System.out.println("Out of memory error thrown by the program");
        }

        /*
         * Checking the memory reference of softReference object,after making
         * the becameSoftReferenceObject = null, as GC is called when
         * OutOfMemoryError is occurred
         */

        System.out.println("Checking the softReference object reference value-"
                + softReference.get());

        System.out.println("*****Execution Completed*****");

    }

    public static class ReferenceClass {
        protected void finalize() {
            System.out
                    .println("Calling the finalize method of ReferenceClass(a static inner class), Soft reference is now removed");
        }
    }

}


Weak Reference Implementaion

/*
 * A weak reference, isn't strong enough to force an object to remain in memory. 
 */
package com.gaurav.javareferences;

import java.lang.ref.WeakReference;

public class WeakReferenceExample {

    public static void GrabgecollectionCall() {
        try {
            System.out.println("Call for the garbage collection");
            System.gc();
            System.out.println("Thread is Sleeping now for 3S");
            Thread.sleep(3000); // for 3 seconds.
        } catch (InterruptedException ie) {
            ie.getMessage();
        }
    }

    public static void main(String args[]) {

        System.out.println("For the Creation of a weak reference object");

        // This is now a weak reference.
        // The object will be collected only if no strong references are
        // available.
        ReferenceClass becameWeakReferenceObject = new ReferenceClass();
        WeakReference<ReferenceClass> weakReference = new WeakReference<ReferenceClass>(
                becameWeakReferenceObject);

        // Trying to remove the to reference and claim memory from suggested
        // reference.
        WeakReferenceExample.GrabgecollectionCall();

        System.out.println("Removing reference by assigning the StrongReference with Null");

        // Checking the memory reference of weakReference object,before
        // making
        // the becameSoftReferenceObject = null

        System.out
                .println("Checking the softReference object reference value before GC call-"
                        + weakReference.get());

        // The object will be garbage collected when the
        // becameWeakReferenceObject is not having any reference .
        becameWeakReferenceObject = null;

        WeakReferenceExample.GrabgecollectionCall();

        /*
         * Checking the memory reference of weakReference object,after making
         * the becameWeakReferenceObject = null, as GC is called when when
         * object is not having any reference.
         */

        System.out
                .println("Checking the WeakReference object reference value after GC call-"
                        + weakReference.get());

        System.out.println("*****Execution Completed*****");

    }

    public static class ReferenceClass {
        protected void finalize() {
            System.out
                    .println("Calling the finalize method of ReferenceClass(a static inner class), Weak reference is now removed");
        }
    }

}

Phantom Reference Implementaion

/*   
 PhantomReference :-

 It allows us to determine the exact moment of removing an object from memory.    It can be needed in work with very big images,

 when it is required to clean complete image from memory, before another image starts loading, to prevent from OutOfMemoryError.

 */
package com.gaurav.javareferences;

import java.lang.ref.PhantomReference;
import java.lang.ref.Reference;
import java.lang.ref.ReferenceQueue;
import java.util.HashMap;
import java.util.Map;

public class PhantomReferenceExample {

    public static void GrabgecollectionCall() {
        try {
            System.out.println("Call for the garbage collection");
            System.gc();
            System.out.println("Thread is Sleeping now for 3S");
            Thread.sleep(3000); // for 3 seconds.
        } catch (InterruptedException ie) {
            ie.getMessage();
        }
    }

    @SuppressWarnings({ "unchecked", "rawtypes" })
    public static void main(String args[]) throws InterruptedException {
        System.out.println("Creating phantom references");

        // The reference itself will be appended to the dead queue for clean up.
        ReferenceQueue referenceQueue = new ReferenceQueue();

        // This map is just a sample we might use to locate resources we need to
        // clean up.
        Map<Reference, String> freeMemoryMap = new HashMap<Reference, String>();

        // Below reference is now became a phantom reference.
        // The object will be collected only if no strong references are
        // available.
        ReferenceClass phantomRefObject = new ReferenceClass();

        PhantomReference<ReferenceClass> phantom = new PhantomReference(
                phantomRefObject, referenceQueue);

        freeMemoryMap.put(phantom, "PhantomReference object Value");

        phantomRefObject = null;

        // The object may now be garbage collected
        PhantomReferenceExample.GrabgecollectionCall();

        // Check for
        Reference reference = referenceQueue.poll();
        if (reference != null) {
            System.out
                    .println("Removing the key of PhantomReference from Map - "
                            + freeMemoryMap.remove(reference));
        }
        System.out
                .println("After removing the PhantomReference key from cleanUpMap -> "
                        + freeMemoryMap.get(reference));
        System.out.println("*****Execution Completed*****");
    }

    public static class ReferenceClass {
        // If there is a finalize() method then PhantomReference's doesn't
        // get appended to a ReferenceQueue

    }

}

No comments:

Post a Comment