Does the GC guarantee that cleared links are placed in the ReferenceQueue in topological order?

Let's say there are two objects: A and B , and there is a pointer Ax --> B , and we create, say, WeakReference , for both A and B , with the associated ReferenceQueue .

Suppose that both A and B become inaccessible. Intuitively, B cannot be considered unreachable to A In this case, we somehow get a guarantee that the corresponding links will be exposed in the intuitive (topological, if there are no cycles) order in the ReferenceQueue ? That is, ref (A) before ref (B). I don’t know - what if the GC marked a bunch of objects as unreachable, and then out of turn in their absence?

I looked at Finalizer.java from guava, seeing this snippet:

 private void cleanUp(Reference<?> reference) throws ShutDown { ... if (reference == frqReference) { /* * The client no longer has a reference to the * FinalizableReferenceQueue. We can stop. */ throw new ShutDown(); } 

frqReference is a PhantomReference to the used ReferenceQueue , so if it is GC'ed, Finalizable links {Weak, Soft, Phantom} cannot be live, because they refer to the queue. Therefore, they must be GC'ed before the queue itself can be GC'ed - but still we get the guarantee that these links will be queued in the ReferenceQueue in the order in which they receive the "garbage collection" (as if do they get gc'ed one by one)? The code implies that there is some kind of guarantee, otherwise raw links could theoretically remain in the queue.

thanks

+4
source share
3 answers

There is no guarantee of the order. In the case of Finalizer.java, the stream may be disconnected before all links are processed. See Docs for FinalizableReferenceQueue:

  • Keep a strong link to this object until all related

  • referents were completed. If this object is previously garbage collected,
  • the support thread will not call {@code finalizeReferent ()} on
  • remaining links.

This is intentional behavior. For example, we use FRQ to clear map records when references to keys and / or values ​​are cleared. If the user no longer has a link to the map and, in turn, no longer has a link to FRQ, it makes no sense to process these links.

+3
source

I am sure there is no answer.

The JVM specification talks about finalizer methods:

The Java virtual machine does not need to be ordered at the end of method calls. Finalizers can be called in any order or even at the same time. ( JVM Specification 2.17.7 )

From this I conclude that there is no guarantee that links are queued in a topological order.

+4
source

I think there is no such guarantee. The GC itself does not have a complete and immediate representation of RAM (it cannot, because the GC runs on a processor that can only look at a few bytes at a time). In your example, assuming the underlying β€œlabel and sweep” of GC, it is likely that A and B will be declared unreachable in the same label phase and grouped in a specific order. Maintaining a topological order is likely to be costly.

As for Finalizer , it seems to be intended to be used only with an instance of FinalizableReferenceQueue , which does some magic related to loading classes. Finalizer uses its capabilities to detect when the FinalizableReferenceQueue , on which it is functionally dependent, becomes inaccessible; this is the moment when the thread that Finalizer running knows that it should exit. From what I understand, if the application allows GC to return FRQ, then the finalizer thread will exit, and any links marked "after" FRQ links will not be processed. It depends on the topological order or its absence, but I cannot decide whether this is a problem or not. I think the application should not discard its FRQ if handling the corrected reference objects is important.

+1
source

Source: https://habr.com/ru/post/1304831/


All Articles