I see below implementation of LRU cache in a legacy project where I have a question on usage of SoftReference
for value object but not for key object.
Here is the implementation
public class LRUCacheImpl<K, V> implements LRUCache<K, V> {
// SoftReference is used for a memory friendly cache.
// The value will be removed under memory shortage situations and
// the keys of the values will be removed from the cache map.
private final Map<K, SoftReference<V>> cache;
public LRUCacheImpl(final int cacheSize) {
// 'true' uses the access order instead of the insertion order.
this.cache = new LinkedHashMap<K, SoftReference<V>> (cacheSize, 0.75f, true) {
private static final long serialVersionUID = 1L;
@Override
protected boolean removeEldestEntry(Map.Entry<K, SoftReference<V>> eldest) {
// When to remove the eldest entry i.e. Least Recently Used (i.e. LRU) entry
return size() > cacheSize; // Size exceeded the max allowed.
}
};
}
@Override
public V put(K key, V value) {
SoftReference<V> previousValueReference = cache.put(key, new SoftReference<V>(value));
return previousValueReference != null ? previousValueReference.get() : null;
}
@Override
public V get(K key) {
SoftReference<V> valueReference = cache.get(key);
return valueReference != null ? valueReference.get() : null;
}
}
GC reclaims the memory for softly reachable objects if application is about to reach OutOfMemory(OOM).
If I apply the same logic, only memory for value should be reclaimed (as soft reference is created for value object only).
But here is the comment in the beginning of file
// SoftReference is used for a memory friendly cache. // The value will be removed under memory shortage situations and // the keys of the values will be removed from the cache map.
My question is how corresponding key object will be removed from map once app reach OOM. Should not the key be wrapped with soft reference as well?
cache.put(new SoftReference<K>(key), new SoftReference<V>(value));