Search code examples
javagarbage-collectionjvmweak-referencesdalvik

Java GC: How does Java GC clears WeakReference object?


First of all I want to let you know that this is more theoretical question than practical, I'm just curious how weakly referenced objects are deallocated.
Let's quickly remember what weak reference is in Java. Roughly speaking WeakReference means deallocate "me" any time you want when there are no strong references that are pointing to "me" until that "I" will remain alive. Also, we know that there are a lot of different garbage collectors that are using different collection techniques. For example, in the past Android was based on Dalvik GC which was stop-the-world, which literally means that the app was suspended during memory cleaning. Later Dalvik was replaced with ART - new version of GC written by Google which is much faster since it is concurrent. So, now comes my question - assume that we have an object that is weakly referenced from some point of the code and there are no strong references to this object, this means that we can access and use this object as usual until collector will not decide to reclaim its space. So, what will happen if the collector will try to deallocate the memory retained by this weakly referenced object exactly during accessing it via WeakReference? I mean the code calls get() method from WeakRefernce class "exactly" at the same time when collectors decides to free its memory. Theoretically it is possible with both types of GC techniques I described above. Since stop-the-world GC suspends the app - the app may be suspended "exactly" when it is accessing this object! For concurrent GCs it is even easier - GC happens concurrently to the app execution.
Again this is a theoretical question, I not 100% sure that it is even possible! Just trying to understand such an edge case of Java world.
Thank you !
Regards,
Andre


Solution

  • It is not that easy. To keep the heap consistent - you don't access the heap directly (at least when GC is active), you access it via some indirection that a typical GC creates. You can think about it as a "proxy", in the GC world - these are called barriers. here is one example of how a certain HotSpot Collector does it, or you might want to read this also.

    In very, very simplified words that "exactly during accessing", is not exactly. It will be an atomic CAS operation for a concurrent cycle, but if it is a stop-the-world cycle - things are far more trivial. So you can never access a WeakReference::get at the same exact time a GC acts on it. If you could and a GC would allow that, heap consistency would be gone and so is any guarantee about your code working.

    My last point is that unless google invented (and patented an algorithm to process WeakReferences concurrently), WeakReferences (and Soft/Phantom/Finalizer) are processed under a full pause.