Item 7: Avoid finalizers

1.  Finalizers are unpredictable, often dangerous, and generally unnecessary. As a rule of thumb, you should avoid finalizers.

 

2.  One shortcoming of finalizers is that there is no guarantee they’ll be executed promptly. This means that you should never do anything time-critical in a finalizer.

 

3.  It is a grave error to depend on a finalizer to close files, because open file descriptors are a limited resource.

 

4.  The promptness with which finalizers are executed is primarily a function of the garbage collection algorithm, which varies widely from JVM implementation to JVM implementation.

 

5.  Providing a finalizer for a class can, under rare conditions, arbitrarily delay reclamation of its instances. Because the finalizer thread runs at a lower priority than another application thread, so objects may not get finalized at the rate they become eligible for finalization.

 

6.  Java language specification provides no guarantee that finalizers will get executed at all. A program may terminate without executing finalizers on some objects that are no longer reachable. As a consequence, you should never depend on a finalizer to update critical persistent state.

 

7.  System.gc and System.runFinalization may increase the odds of finalizers getting executed, but they don’t guarantee it.

 

8.  If an uncaught exception is thrown during finalization, the exception is ignored, and finalization of that object terminates. Uncaught exceptions can leave objects in a corrupt state. If another thread attempts to use such a corrupted object, arbitrary nondeterministic behavior may result.

 

9.  There is a severe performance penalty for using finalizers.

 

10.  Provide an explicit termination method which should do whatever is required to free the critical resource and require clients of the class to invoke this method on each instance when it is no longer needed. The instance must keep track of whether it has been terminated: 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.( Such as close methods on InputStream, OutputStream and java.sql.Connection. )

 

11.  The cancel method on java.util.Timer, which performs the necessary state change to cause the thread associated with a Timer instance to terminate itself gently.

 

12.  Image.flush deallocates all the resources associated with an Image instance but leaves it in a state where it can still be used, reallocating the resources if necessary.

 

13.  Explicit termination methods are typically used in combination with the try-finally construct to ensure termination. Invoking the explicit termination method inside the finally clause ensures that it will get executed even if an exception is thrown while the object is being used.

 

14.  One legitimate use for finalizer is to act as a “safety net” in case the owner of an object forgets to call its explicit termination method. But the finalizer should log a warning if it finds that the resource has not been terminated. Think long and hard about whether the extra protection is worth the extra cost. FileInputStream, FileOutputStream, Timer, and Connection have finalizers that serve as safety nets in case their termination methods aren’t called but they don’t log warnings.

Commented by Sean: Timer doesn't do that in JDK 7.

 

15.  A second legitimate use of finalizers concerns objects with native peers. A native peer is a native object to which a normal object delegates via native methods. A finalizer is an appropriate vehicle for performing this task, assuming the native peer holds no critical resources.

 

16.  The subclass finalizer must invoke the superclass finalizer manually. You should finalize the subclass in a try block and invoke the superclass finalizer in the corresponding finally block. This ensures that the superclass finalizer gets executed even if the subclass finalization throws an exception.

 

17.  Instead of putting the finalizer on the class requiring finalization, put the finalizer on an anonymous class whose sole purpose is to finalize its enclosing instance. It’s called finalizer guardian:

// Finalizer Guardian idiom
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
}

so it doesn’t matter whether a subclass finalizer calls super.finalize or not.

你可能感兴趣的:(finalize,Finalizer)