NOTE
- Never do anything time-critical in a finalizer.
- Never depend on a finalizer to update critical persistent state.
- There is a severe performance penalty for using.
-
"Finalizer chaining" is not performed automatically. The subclass finalizer must invoke the superclass finalizer manually.
- Manual finalizer chaining
@Override
protected void finalize() throws Throwable {
try {
... // Finalize subclass state
} finally {
super.finalize();
}
}
b. Finalizer Guardian idiom
// Finalizer Guardian idiom. This will prevent the subclass forgets to invoke super class's finalize method.
public class Foo {
// Sole purpose of this object is to finalize outer Foo object
private final Object finalizerGuardian = new Object() {
@Override protected void finalize() throws Throwable {
... // Finalize outer Foo object
}
};
... // Remainder omitted
}
What to do
- Provide an explicit termination method
the explicit termination method must record in a private field that the object is no longer valid, and other methods must check this field and throw an IllegalStateException if they are called after the object has been terminated.
-
Explicit termination methods are typically used in combination with the try-finally construct to ensure termination.
// try-finally block guarantees execution of termination method
Foo foo = new Foo(...);
try {
// Do what must be done with foo
...
} finally {
foo.terminate(); // Explicit termination method
}
Usage of finallizer
-
Safety net: ensure the resources being released even if the explicitly termination method is not executed correctly.
Note: the finalizer should log a warning if it finds that the resource has not been terminated
- Concerns objects with native peers. A native peer is a native object to which a normal object delegates via native methods. Because a native peer is not a normal object, the garbage collector doesn't know about it and can't reclaim it when its Java peer is reclaimed. A finalizer is an appropriate vehicle for performing this task, assuming the native peer holds no critical resources.
Summary
In summary, don't use finalizers except as a safety net or to terminate noncritical native resources. In those rare instances where you do use a finalizer, remember to invoke super.finalize. If you use a finalizer as a safety net, remember to log the invalid usage from the finalizer. Lastly, if you need toassociate a finalizer with a public, nonfinal class, consider using a finalizer guardian, so finalization can take place even if a subclass finalizer fails to invoke super.finalize.