The finalization problem is a problem of many languages which support GarbageCollection. Many such languages provide finalizers - methods to be called when the object is to be discarded. (The "final" method in JavaLanguage, etc.) However, the presence of these can complicate GC semantics, for the following reasons:
- When the finalizer is called is indeterminate. Some languages allow it to be called on live objects; others don't call it unless the object is dead (no references); others make finalization optional or best-effort.
- If the finalizer is called on a dead object, there is the possibility that it may resurrect the object by creating a new valid reference to it (one runs into the same problem when dealing with WeakPointers). What then?
- If a cycle is reclaimed; in what order are the finalizers called? Should it matter?
Some claim finalizers aren't useful (or shouldn't be) in a purely garbage-collected system where resources are not scarce, that might be true. In practical systems, there are many resources (files, other kernel objects, distributed thingies) which a) are outside the scope of the
GarbageCollector (though it's good practice to wrap these in objects as soon as possible); b) sufficiently scarce that the inderministic behavior of a
GarbageCollector is an inappropriate management strategy; c) have explicit "cleanup" semantics besides the releasing of resources (such as flushing buffers when closing files). Hence, finalizers.
It should be noted that C++ destructors are similar, but not the same. C++ destructors are deterministic when it comes to when they are executed, and handle many more things (such as memory management).
Interestingly enough, sometimes finalizers are not enough. Java has finalizers, but many objects implement a DestroyMethod which performs resource de-allocation and subsequently invalidates the object (see ObjectInvalidation). Client code is expected to call destroy() when appropriate (a finalizer is provided which does this automatically - assuming it is run - should the client forget).
Possible solutions to the FinalizationProblem.
- No finalization. Some view GarbageCollection as a way of simulating infinite memory; in this case, dead objects never really get destroyed they just disappear.
- Best effort finalization. Finalizers are called on a best-effort basis (note that in many GarbageCollectors?; garbage is collected on a best-effort basis; some generational and conservative garbage collectors don't collect all the trash).
- One-shot finalization. This is what Java does; a finalizer can resurrect an object but its finalize method won't be called more than once.
- ObjectInvalidation. The object becomes invalid when the finalizer is run; any subsequent attempts to reference it (if the object is resurrected) result in an exception.
- SelfRevokation?. The finalize method no longer has a user-accessible this (or self) parameter - essentially the object becomes second-class. (In particular, one can no longer do foo = this.)
See also:
DeterministicFinalization FinalizeInsteadOfProperDestructor DeterministicResourceManagement