Search code examples
javareferencegarbage-collectionjvmg1gc

Which reference Finalizer (FinalReference) or Weak/Phantom/Soft Reference have higher priority for GC


When object with non-trivial finalize() method is created, JVM will create Finalizer (FinalReference) with this object as referent. What will happen if this object will be also wrapped by Soft/Weak or Phantom Reference? Would GC try to enqueue the Finalizer (call finalize method on it) at first, and then enqueue the other Reference or the opposite?


Solution

  • I think, your question is not about the time of enqueuing, actually.

    Consider the Notification section of the package documentation

    Some time after the garbage collector determines that the reachability of the referent has changed to the value corresponding to the type of the reference, it will add the reference to the associated queue.

    (Note the “some time after”)

    and likewise, all reference types have a statement of the form:

    Suppose that the garbage collector determines at a certain point in time that an object is weakly reachable. At that time it will atomically clear all weak references to that object and all weak references to any other weakly-reachable objects from which that object is reachable through a chain of strong and soft references. At the same time it will declare all of the formerly weakly-reachable objects to be finalizable. At the same time or at some later time it will enqueue those newly-cleared weak references that are registered with reference queues.

    (taken from the WeakReference; Note the “at the same time or at some later time”)

    In practice, the garbage collector hands over the discovered references to another thread which does the enqueuing asynchronously. Since an unspecified delay makes the order in which an application will retrieve the references from a queue undeterministic, it’s pointless to ask about an order here.

    However, I suppose, you’re actually interested in the other “certain point in time”, when “the garbage collector determines that the reachability of the referent has changed to the value corresponding to the type of the reference” and will decide to clear the references atomically and make them eligible for enqueuing.

    When there is a mixture of multiple differently typed reference objects, including a Finalizer reference, but no strong reference, there are two possible scenarios:

    1. There is at least one soft reference and there is no memory pressure. Then, the garbage collector may decide not clear resp. enqueue any reference.
    2. There is no soft reference or the garbage collector decides that memory pressure justifies clearing soft references. Then all soft and weak references are cleared and all soft, weak, and finalizer references are handed over for enqueuing.
      Only phantom references stay untouched.

    Note that once finalization started, there is no Finalizer reference anymore, but during finalization, new soft or weak reference might get created. So the resulting scenarios are the same as with the optimized handling of objects having a trivial finalize() method. There can be a mixture of soft, weak, and phantom references, without a Finalizer reference. When there is no remaining strong reference, we again have the two possible scenarios:

    1. There is at least one soft reference and there is no memory pressure. Then, the garbage collector may decide not clear resp. enqueue any reference.
    2. There is no soft reference or the garbage collector decides that memory pressure justifies clearing soft references. Then all soft, weak, and phantom references are clearedA and all soft, weak, and phantom references are handed over for enqueuing.

    A phantom references are cleared in Java 9 or newer. In previous versions they are only enqueued without being cleared.