Sunday, 17 April 2011

WeakHashMap in java : Soft reference based hashmap

A WeakHashMap stores the keys using WeakReference objects, which means that as soon as the key is not referenced from somewhere else in your program, the entry may be removed and is available for garbage collection. Otherwise it is similar to HashMap.

One of the most common instances of memory leaks in Java is in hash maps, so Sun Microsystems (now Oracle) has provided a WeakHashMap to minimize memory usage in caches implemented with maps. A WeakHashMap stores the keys using WeakReference objects, which means that as soon as the key is not referenced from somewhere else in your program, the entry may be removed and is available for garbage collection. (Have a look at the JavaDocs for the java.util.WeakHashMap and java.lang.ref.WeakReference for more information). It is important to note that the WeakHashMap has a WeakReference to the key—rather than, as we would expect—the value.

Read about type of references here.
 
As the garbage collector may remove keys from the WeakHashMap and garbage collect the object, outputs from methods like size() , isEmpty() may vary with time. The size( ) method may return different values over time. The isEmpty( ) method may return false and then true.
 
Note: Value objects in the WeakHashMap will be garbage collected only if their key is removed and they have no other reference to them. It should be noted that if the value object has a reference to its own key object, the key objetc will not be garbage collected. This situation should be avoided.

WeakHashMap Example:
public class TestWeakHashMap {
public static void main(String[] args) {
WeakHashMap map=new WeakHashMap();

String s1=new String("java");
map.put(s1, "good");
String s2=new String("java");
map.put(s2,"ok");

//Since s1.equals(s2) is true and hash is same, the earlier value
//against key s1 ("good") in the map is replaced by the new one. ("ok")

s1=null;

System.gc();
//Verify Full GC with the -verbose:gc option

System.out.println(map.size());
}
}


Here s1 and s2 are two different objects on the heap. So in line 5, a new (key,value) pair with key s1 is put into the map. Later when a (key,value) with key s2 is being put into the map, it checks for equals on s1 and s2 and their hashcode. When it finds the equals returns true and hashCode is same, it replaces the value of the earlier entry with the new value. But the issue here is, WeakHashMap/HashMap does not replace the earlier key while adding a (key, value) pair whose key is actually a duplicate key in the map.
So even after putting an entry with key s2, the WeakHashMap has only one entry whose key refers to the object refered by s1 and not s2.

Now the object on the heap refered by s1, has one strong reference(through s1) and one weak reference through the WeakHashMap.
Later when I say s1=null, the object on the heap refered to by s1 lost the strong reference and when gc happens, the entry is removed from the map.

So thats how it works.

Also note WeakHashMap is only a wrapper over HashMap and the HashMap's put api says " If the map previously contained a mapping for this key, the old value is replaced by the specified value."

Also see -

No comments:

Post a Comment