Search code examples
javacachingguavasoft-references

Implementation of a cache using soft references both for keys and values


I'd like to implement a cache whose keys and values are soft references because the instances that it will contain can take a long time to be computed (especially the values) and I'd like the entries containing unreferenced objects as keys or as values to get garbage collected if and only if I may run out of memory. If I used weak references for the values, they would be garbage collected as soon as they aren't referenced which isn't what I want to do.

At first, I used this example. It works but creating a single thread per cache instance annoys me, it uses strong references for the keys and expunging stale entries by myself (like WeakHashMap) in some method calls of the cache class doesn't work (obviously) when I risk to run out of memory when I don't call them. I wanted to use Guava but MapMaker does no longer allow the use of soft keys which is logical as the default equivalence is based on equality (==) and not on the equals() method which means that it's impossible to recreate an identical key. However, I agree with sebastien-lorber's comment:

i think soft keys would make sense if Guava was overriding equals method of the SoftReference. I've seen that Guava uses an "equivalence mecanism" and i think, for soft references, the defaultEquivalence should not be identity but equals, to handle such a case.

I looked at MapDB and JCS too.

How can I modify the example I quoted above or use Guava to make a cache based on soft references, preferably using equals() instead of == to determine the equality of keys?


Solution

  • Actually, I've just reintroduced soft keys in Guava (removed from it in version 14) but in CacheBuilder: https://code.google.com/p/guava-libraries/issues/detail?id=1845

    Then, I have to call the non public method CacheBuilder.keyEquivalence(Equivalence.equals()) in order to use equals() instead of == to compare keys. I'll let you know whether it works. I'll accept my own answer in this case. Otherwise, I'll have to use maaartinus's suggestions.