Java Reference
In-Depth Information
erent won't happen. This kind of error is reason enough why finalizers should be used as sel-
dom as possible.
Unfortunately, finalizers are unavoidable in certain circumstances. The JDK, for example,
uses a finalizer in its classes that manipulate ZIP files, because opening a ZIP file uses some
native code that allocates native memory. That memory is freed when the ZIP file is closed,
but what happens if the developer forgets to call the close() method? The finalizer can en-
sure that the close() method has been called, even if the developer forgets that.
As a rule, then, if you are in a situation where a finalizer is unavoidable, make sure that the
memory accessed by the object is kept to a minimum.
There is an alternative to using finalizers that avoids at least some of these problems—and in
particular, it allows the referent to be freed during normal GC operations. This is accom-
plished by simply using another kind of indefinite reference rather than implicitly using a
Finalizer reference.
It is sometimes recommended to use yet another indefinite reference type for this: the
PhantomReference class. That's a good choice, because the reference object will be cleaned
up relatively quickly once the referent is no longer strongly referenced, and while debugging,
the purpose of the reference is clear. Still, the same goal can be achieved with a weak refer-
ence (plus, the weak reference can be used in more places). And in certain circumstances, a
soft reference could be used if the caching semantics of the soft reference match the need of
the application.
To create a substitute finalizer, you must create a subclass of the indefinite reference class to
hold any information that needs to be cleaned up after the referent has been collected. Then
you perform the cleanup in a method of the reference object (as opposed to defining a fi-
nalize() method in the referent class).
private
private static
static class
class CleanupFinalizer
CleanupFinalizer extends
extends WeakReference {
private
private static
static ReferenceQueue < CleanupFinalizer > finRefQueue ;
private
private static
static HashSet < CleanupFinalizer > pendingRefs = new
new HashSet <>();
private
private boolean
boolean closed = false
false ;
public
public CleanupFinalizer ( Object o ) {
super
super ( o , finRefQueue );
allocateNative ();
pendingRefs . add ( this
this );
}
Search WWH ::




Custom Search