Davy Landman
Davy Landman

Reputation: 15438

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.

Upvotes: 4

Views: 480

Answers (2)

Holger
Holger

Reputation: 298469

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.

Upvotes: 6

Eugene
Eugene

Reputation: 120988

It seems to me you have more than one question. The first is when a reference will appear on the reference queue.

The documentation (on purpose?) leaves room for interpretation, taken from here:

Provides reference-object classes, which support a limited degree of interaction with the garbage collector. A program may use a reference object to maintain a reference to some other object in such a way that the latter object may still be reclaimed by the collector. A program may also arrange to be notified some time after the collector has determined that the reachability of a given object has changed.

So, it happens some time after. Under the current implementation it is an async process, so the documentation is not wrong.

The second question you have starts with a false premises:

... GC will come around and collect the SoftReference...

Not really. GC will not even know about the existence of this SoftReference if it is not reachable. GC finds alive objects and everything else is garbage, as weird as it might sound. As such GC will not even know that there was a SoftReference as it never visits it. When this happens, nothing is put on the ReferenceQueue. For that to happen that SoftReference needs to be traversed, but since that never happened...

Simply because a SoftReference is unreachable does not imply the same about the referent. It is perfectly valid for the referent to be strongly reachable, but for the SoftReference to be unreachable.

To your last point (that I imply you will care about): when SR is reachable, but referent is dead. When GC discovers such a thing, it's supposed to clear the referent (subsequent get will return null) and post that on the ReferenceQueue, right? Well, almost. This depends on the actual GC. For a contra-example, take Shenandoah GC that has a flag called ShenandoahRefProcFrequency (defaults to 5). It shows how often should Weak References be cleared, if it's not 5, when such a scenario happens : the referent is declared "alive". This referent is kept artificially alive until that limit is hit.

Upvotes: 4

Related Questions