Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

WeakHashMap iteration and garbage collection

Tags:

java

I am using a WeaekHashMap to implement a Cache. I am wondering if I am iterating over the keys of this map, and at the same time garbage collector is actively removing keys from this map, would I receive a ConcurrentModificationException ? I do not think so, because as far as I understand, concurrentmodificationexception happens because of bugs in the application code where the developer forgot to understand that the same map is shared/used by other threads and in this case, it should not happen. But wondering how would JVM handle this when WeakHashMap is not synchronized ?

like image 671
Shamik Avatar asked May 18 '10 21:05

Shamik


People also ask

What is WeakHashMap in collection framework?

WeakHashMap is an implementation of the Map interface that stores only weak references to its keys. Storing only weak references allows a key-value pair to be garbage-collected when its key is no longer referenced outside of the WeakHashMap. This class provides the easiest way to harness the power of weak references.

What is difference between HashMap and WeakHashMap?

WeakHashMap is almost same as HashMap except in case of WeakHashMap, if object is specified as key doesn't contain any references- it is eligible for garbage collection even though it is associated with WeakHashMap. i.e Garbage Collector dominates over WeakHashMap.

What is true about a WeakHashMap garbage collector?

An entry in a WeakHashMap will automatically be removed when its key is no longer in ordinary use. More precisely, the presence of a mapping for a given key will not prevent the key from being discarded by the garbage collector, that is, made finalizable, finalized, and then reclaimed.


2 Answers

As bkail said, when GC "removes" an entry from a WeakHashMap it is not going to cause a concurrent modification. In reality the GC collects the underlying object by there is a hard reference to WeakReference object (that holds the real key) itself. Therefore, the real object (the reference object) that is directly referenced by the map is not collected so the map does not change until one of your threads calls a method in this map. At that time the map checks the reference queue from the GC and finds all keys that have been collected and removes them from the map - so the actual changes to the map structure occurs on one of your threads.

In thinking of this then there may be one case where you may get a concurrent modification in such a map that you would not get in another kind of map - if you put a key that already exists or call a getter method. But really, in a concurrent application you should be locking around these calls anyway so you would have a really concurrent access bug in your program.

That being said in answer to your question, you really should not use WeakHashMap for a cache (even if you were talking about caching keys). In a cache you don't want your values 'magically' disappearing when the values are no longer referenced. Typically you want them to disappear when there is a certain maximum number (something like Apache collections LRUMap) or released on memory demand.

For the later, you can use a map with a SoftReference (Apache collections provides a ReferenceMap that allows you to specify the kind of reference for either the key or value). A soft reference is specified to only be released based on memory pressure - a weak reference on the other hand has to do more with GC recognizing that there are no hard reference remaining to the object and can release it at any time. Of course, how a soft reference really works is also dependent on the JVM implementation.

EDIT: I reread your question and want to address one other point. Because the actual modifications occur to the WeakHashMap internal structures on your own thread, if you only use this map in a single thread you do not need to synchronize any method calls. This behavior is no different than any other Map.

like image 96
Kevin Brock Avatar answered Sep 18 '22 17:09

Kevin Brock


No, you will not receive ConcurrentModificationException. WeakHashMap uses ReferenceQueue.poll when you call various operations. In other words, each caller is silently responsible for clearing stale entries from the Map. However, that does mean that it is not safe to call methods on a WeakHashMap from multiple threads that would otherwise seem to be "read-only" because any call to get() can destroy the entry linked list that another thread is attempting to iterate.

like image 37
Brett Kail Avatar answered Sep 17 '22 17:09

Brett Kail