|
|
|
Advertisement
|
Finalizers to avoid
The central rule of thumb concerning finalizers is this:
Don't design your Java programs such that correctness depends upon "timely" finalization.
In other words, don't write programs that will break if certain objects aren't finalized by certain points in the life of the program's execution. If you write such a program, it may work on some implementations of the JVM but fail on others.
Don't rely on finalizers to release non-memory resources
An example of an object that breaks this rule is one that opens a file
in its constructor and closes the file in its finalize()
method. Although this design seems neat, tidy, and symmetrical, it
potentially creates an insidious bug. A Java program generally will
have only a finite number of file handles at its disposal. When all
those handles are in use, the program won't be able to open any more
files.
A Java program that makes use of such an object (one that opens a file in its constructor and closes it in its finalizer) may work fine on some JVM implementations. On such implementations, finalization would occur often enough to keep a sufficient number of file handles available at all times. But the same program may fail on a different JVM whose garbage collector doesn't finalize often enough to keep the program from running out of file handles. Or, what's even more insidious, the program may work on all JVM implementations now but fail in a mission-critical situation a few years (and release cycles) down the road.
Other finalizer rules of thumb
Two other decisions left to JVM designers are selecting the thread (or
threads) that will execute the finalizers and the order in which
finalizers will be run. Finalizers may be run in any order --
sequentially by a single thread or concurrently by multiple threads. If
your program somehow depends for correctness on finalizers being run in
a particular order, or by a particular thread, it may work on some JVM
implementations but fail on others.
You should also keep in mind that Java considers an object to be
finalized whether the finalize() method returns normally
or completes abruptly by throwing an exception. Garbage collectors
ignore any exceptions thrown by finalizers and in no way notify the
rest of the application that an exception was thrown. If you need to
ensure that a particular finalizer fully accomplishes a certain
mission, you must write that finalizer so that it handles any
exceptions that may arise before the finalizer completes its mission.
One more rule of thumb about finalizers concerns objects left on
the heap at the end of the application's lifetime. By default, the
garbage collector will not execute the finalizers of any objects left
on the heap when the application exits. To change this default, you
must invoke the runFinalizersOnExit() method of class
Runtime or System, passing true
as the single parameter. If your program contains objects whose
finalizers must absolutely be invoked before the program exits, be sure
to invoke runFinalizersOnExit() somewhere in your
program.
|
Sponsored Links
|