Consider the Reference API.
It offers some references with special semantics to the GC, i.e Weak, Soft, and Phantom references. There’s simply another non-public
type of special reference, for objects needing finalization.
Now, when the garbage collector traverses the object graph and encounters such a special reference object, it will not mark objects reachable through this reference as strongly reachable, but reachable with the special semantics. So if an object is only finalizer-reachable, the reference will be enqueued, so that one (or one of the) finalizer thread(s) can poll the queue and execute the finalize()
method (it’s not the garbage collector itself calling this method).
In other words, the garbage collector never processes entirely unreachable objects here. To apply a special semantic to the reachability, the reference object must be reachable, so the referent can be reached through that reference. In case of finalizer-reachability, Finalizer.register
is called when an object is created and it creates an instance of Finalizer
in turn, a subclass of FinalReference
, and right in its constructor, it calls an add()
method which will insert the reference into a global linked list. So all these FinalReference
instances are reachable through that list until an actual finalization happens.
Since this FinalReference
will be created right on the instantiation of the object, if its class declares a non-trivial finalize()
method, there is already some overhead due to having a finalization requirement, even if the object has not collected yet.
The other issue is that an object processed by a finalizer thread is reachable by that thread and might even escape, depending on what the finalize()
method does. But the next time, this object becomes unreachable, the special reference object does not exist anymore, so it can be treated like any other unreachable object.
This would only be a performance issue, if memory is very low and the next garbage collection had to be performed earlier to eventually reclaim that object. But this doesn’t happen in the reference implementation (aka “HotSpot” or “OpenJDK”). In fact, there could be an OutOfMemoryError
while objects are pending in the finalizer queue, whose processing could make more memory reclaimable. There is no guaranty that finalization runs fast enough for you’re purposes. That’s why you should not rely on it.
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…