Saturday, July 15, 2017

SoftReference vs WeakReference


In Java; order from strongest to weakest, there are: Strong, Soft, Weak and Phantom
  • A Strong reference is a normal reference that protects the referred object from collection by GC. i.e. Never garbage collects.
  • A Soft reference is eligible for collection by garbage collector, but probably won't be collected until its memory is needed. i.e. garbage collects before OutOfMemoryError.... is eligible for collection by garbage collector, but probably won't be collected until its memory is needed for another use ( garbage collector won't collect the reference until the memory is available.)
  • A Weak reference is a reference that does not protect a referenced object from collection by GC. i.e. garbage collects when no Strong or Soft refs.
  • A Phantom reference is a reference to an object is phantomly referenced after it has been finalized, but before its allocated memory has been reclaimed.
Analogy: Assume a JVM is a kingdom, Object is a king of the kingdom, and GC is an attacker of the kingdom who tries to kill the king(object).
  1. When King is Strong, GC can not kill him.
  2. When King is Soft, GC attacks him but King rule the kingdom with protection until resource are available.
  3. When King is Weak, GC attacks him but rule the kingdom without protection.
  4. When king is Phantom, GC already killed him but king is available via his soul.

Weak references are collected eagerly. If GC finds that an object is weakly reachable (reachable only through weak references), it'll clear the weak references to that object immediatel

SoftReferences on the other hand are good for caching external, recreatable resources as the GC typically delays clearing them.

Principle : weak reference is related to garbage collection. Normally, object having one or more reference will not be eligible for garbage collection.

The above principle is not applicable when it is weak reference. If an object has only weak reference with other objects, then its ready for garbage collection.

Let's look at the below example: We have an Map with Objects where Key is reference a object.


public class Test {

    public static void main(String args[]) {
        HashMap<Employee, EmployeeVal> aMap = new
                       HashMap<Employee, EmployeeVal>();

        Employee emp = new Employee("Vinoth");
        EmployeeVal val = new EmployeeVal("Programmer");

        aMap.put(emp, val);

        emp = null;

        System.gc();
        System.out.println("Size of Map" + aMap.size());

    }
}

Now, during the execution of the program we have made emp  = null. The Map holding the key makes no sense here as it is null. In the above situation, the object is not garbage collected.

WeakHashMap
WeakHashMap is one where the entries (key-to-value mappings) will be removed when it is no longer possible to retrieve them from the Map.

Let me show the above example same with WeakHashMap

public class Test {

    public static void main(String args[]) {
        WeakHashMap<Employee, EmployeeVal> aMap = 
                    new WeakHashMap<Employee, EmployeeVal>();

        Employee emp = new Employee("Vinoth");
        EmployeeVal val = new EmployeeVal("Programmer");

        aMap.put(emp, val);

        emp = null;

        System.gc();
        int count = 0;
        while (0 != aMap.size()) {
            ++count;
            System.gc();
        }
        System.out.println("Took " + count
                + " calls to System.gc() to result in weakHashMap size of : "
                + aMap.size());
    }
}

Output : Took 20 calls to System.gc() to result in aMap size of : 0.

WeakHashMap has only weak references to the keys, not strong references like other Map classes. There are situations which you have to take care when the value or key is strongly referenced though you have used WeakHashMap. This can avoided by wrapping the object in a WeakReference.



public class Test {

    public static void main(String args[]) {
        HashMap<Employee, EmployeeVal> map = 
                      new HashMap<Employee, EmployeeVal>();
        WeakReference<HashMap<Employee, EmployeeVal>> aMap = 
                       new WeakReference<HashMap<Employee, EmployeeVal>>(
                map);

        map = null;

        while (null != aMap.get()) {
            aMap.get().put(new Employee("Vinoth"),
                    new EmployeeVal("Programmer"));
            System.out.println("Size of aMap " + aMap.get().size());
            System.gc();
        }
        System.out.println("Its garbage collected");
    }
}

Soft References

Soft Reference is slightly stronger that weak reference. Soft reference allows for garbage collection, but begs the garbage collector to clear it only if there is no other option.

The garbage collector does not aggressively collect softly reachable objects the way it does with weakly reachable ones -- instead it only collects softly reachable objects if it really "needs" the memory. Soft references are a way of saying to the garbage collector, "As long as memory isn't too tight, I'd like to keep this object around. But if memory gets really tight, go ahead and collect it and I'll deal with that." The garbage collector is required to clear all soft references before it can throw

No comments: