In order to perform some testing, I'd like to check how my application behaves when some or all of the objects I have stored in a cache of SoftReference'd objects are disposed of.
In order to do this, I'd like to manually clear the references stored in the cached SoftReference objects - simulating the VM disposing of those objects - but only if nothing else currently has a strong reference to that object (which could be the case if another process had recently retrieved the referenced object from the cache).
My application is single-threaded, so I don't need to worry about the soft reachability of a cached object changing as this code is executing. This also means that I don't currently have any locking mechanisms - if I did have, I could possibly have used these to determine whether or not an object was 'being used' and hence strongly reachable, but alas I don't have need of such locking.
One approach I have tried is to create an additional SoftReference to every object stored in the cache which is registered with a ReferenceQueue. My hope was that in doing so, all of the softly reachable objects in the cache would have their additional SoftReference added to the queue, so all I had to do was loop over the queue, and remove those objects from my cache. However, it seems that the GC enqueues softly reachable objects to their respective queues at its leisure, so it is not guaranteed that anything will be added to the queue once I've finished iterating through the objects in the cache.
One thing that I have also looked at is the -XX:SoftRefLRUPolicyMSPerMB JVM option with a very small value. With judicious memory allocation, this will quite probably clear softly reachable objects from the cache for me the moment they are softly reachable, but I'd really like the app to run normally until I receive a request to clear the softly reachable objects from the cache. As a JVM option, I don't believe I can alter this value while my app is running.
So, does anyone have any ideas as to how I can determine whether or not an object is only softly reachable (and hence can be cleared)?
Edit: The a few extra points that may not have been clear:
- The app will probably be doing useful work at the times that I want to clear these softly reference objects out. So I'd prefer to not try and cause the GC to clear objects out for me.
- It would be preferable if I could select which softly reachable objects were cleared out.
- I would like to app to run normally, i.e. using production memory settings. Changing settings in code, which can then be reset back to their production values, is fine.