3

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

Holger
  • 285,553
  • 42
  • 434
  • 765
Andre Liberty
  • 707
  • 1
  • 9
  • 17
  • 3
    Weak references aren't particularly special in that regard. Imagine a compacting GC that runs in the background - what happens if an app thread tries to access an object that is in the process of being moved around on the heap? Pretty much the same here. One solution and the one that Android uses (at least currently afaik) is a read barrier to intercept reference reads on the heap. – Voo Nov 23 '20 at 14:07
  • 3
    What means “‘exactly’ when it is accessing this object” for a stop-the-world? Either, there is already a strong reference to the referent, because the field has been read, or not. Depending on which state the world is stopped in, the garbage collector will retain the reference or clear it. For a concurrent collector, things are more complicated, but when adapting references to a moved object can be done concurrently, clearing them concurrently should be possible too. But if in doubt, a concurrent GC may simply keep the reference. There is no guaranty that all unreachable objects are discovered – Holger Nov 23 '20 at 15:07
  • 1
    @Holger currently though concurrent collectors, afaik, discover weak references concurrently, but processes them under a pause. – Eugene Nov 23 '20 at 16:06
  • 2
    @Eugene That’s my knowledge too, regarding what happens in the Hotspot JVM, but I don’t know what Google’s ART does. – Holger Nov 23 '20 at 16:08

1 Answers1

2

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.

Eugene
  • 117,005
  • 15
  • 201
  • 306