Java Tricks and Quirks

SoftReference and OutOfMemoryError

We have recently learned an interesting fact about Java's SoftReference and the potential occurence of an OutOfMemoryError. The result first: An OutOfMemoryError may be thrown in a situation where SoftReferences can be released after which enough memory would be available. The reason is that normal garbage collection happens in an independent thread and does not halt other threads when they allocate memory. Only an explicit System.gc() waits until the memory is freed . The consequence is that whenever you allocate memory then you should do that with the following clause:

final MyObject o;
try {
  o = new MyObject();
}
catch (OutOfMemoryError e) {
  System.gc();
  o = new MyObject();
}  

We found this by implementing a simple cache using a HashMap of SoftReferences to an object that on finalize removes the corresponding key in the HashMap. That cache is used to store image tiles for an ImgLib2 backend that uses a CATMAID stack (GitHub). It turned out that the painter thread in an interactive viewer was fetching new tiles quicker than the garbage collector would finalize SoftReferences and stopped with an OutOfMemoryError. We could solve that with the the above construct.