Why is finalize () called only once by the garbage collector?

Quotes from the SCJP 6 study guide:

In the finalize() method, you can write code that passes a link to the object in question, back to another object, effectively immobilizing the garbage collection object. If at some point later the same object again becomes suitable for garbage collection, the garbage collector will still be able to process this object and delete it. However, the garbage collector will remember that finalize() has already been executed for this object, and it will no longer run finalize()

Why is it designed like this? The goal of finalize() is still preserved, even if the object is marked a second time. Then why does Java decide to skip the finalize() call?

+5
source share
2 answers

I don't know if the original reason is, but the current implementation completes the Finalizer instances (internal subclass of Reference ) for objects overriding the finalization method, with an internal ReferenceQueue , which is handled by a special FinalizerThread .

And since the JVM has no way of knowing whether an object should be completed a second time, it cannot decide whether it will include a new Finalizer after the finalize() method is called.

In any case, you should avoid using finalize() . This makes placing objects more expensive, prevents leak analysis, and is not a very reliable way to manage your own resources, as the GC can delay completion for an unlimited period of time.

+4
source

Objects with a finalizer enabled are unsuitable for collection; however, the GC checks them only after identifying all other objects that are not suitable for collection, and marks all objects that would be suitable for collection, but for the existence of an included finalizer, and runs finalize methods on such objects as soon as possible. Finalized objects will not have the right to collect until the finalizer finishes, but the GC will not be able to distinguish between objects that will have the right to finalize as soon as the finalizer finishes, or those that were rejected for finalization as a result of actions using some object finalizer and became available for collection at a later time.

The .NET Framework includes methods called IIRC GC.SuppressFinalize and GC.ReRegisterForFinalization , which allow you to use code that knows the finalizer of the object, nothing good to tell GC to not disturb, calling it, and allows you to use code that knows that the finalizer was running " too soon "to ask him to run later. However, the JVM does not include such a feature. Since all completed objects are automatically re-registered for completion after the finalizer finishes, they will not allow them to be collected, and since there is no way to manually re-register them, there is nothing useful in that there is no way to use a template in which the finalizer of objects can be run more than once .

On the other hand, it is possible to achieve a similar effect by defining an object of a nested class that can be finalized by having an object of an external class containing a reference to an instance of the nested class and the presence of this nested instance of the class to β€œfinalize”, the method will return to clearing the code from its owner. If this cleanup code discards an instance of a nested class and replaces it with a new one, then this new instance starts its finalizer (binding to its owner) in the next GC loop, where the owner detects that it was not found.

+2
source

All Articles