javagarbage-collectionjava-memory-modelsoft-references

When you discard the reference to a SoftReference, will it's clearing still be put on the ReferenceQueue?


I want to understand under which conditions the garbage collector notifies you of clearing a soft reference. The documentation makes it clear it happens when an OOM might occur, but what if you discard the reference completely, GC will come around and collect the SoftReference might notice no other strong/softly references exists and clear the internal referred value.

ReferenceQueue<Object> cleared = new ReferenceQueue<>();
Object X = new Object();
SoftReference<Object> Xs = new SoftReference<>(X, cleared);

Thread.sleep(10);
X = null;
Xs = null;

System.GC();
Thread.sleep(100);
Reference ref;
while ((ref = cleared.poll()) != null) {
   System.err.println(ref);
}

So where are the rules around this queue documentated? There must be more corner cases than what I'm asking, so maybe the question has to be broadened a bit.


Solution

  • The relevant point can be found in the package documentation in the Notification section:

    The relationship between a registered reference object and its queue is one-sided. That is, a queue does not keep track of the references that are registered with it. If a registered reference becomes unreachable itself, then it will never be enqueued. It is the responsibility of the program using reference objects to ensure that the objects remain reachable for as long as the program is interested in their referents.

    So the answer is simple. Since you set the sole variable referencing your SoftReference to null, it will never be enqueued. Whether it will get collected or cleared, doesn’t matter, as you are unable to perceive it. In practice, typical implementations will behave as Eugene wrote, the garbage collector only traverses live references and does not care about what kind of garbage exists within the remaining memory.