The garbage collector invokes object finalizer methods after it has determined that the object is unreachable, but before it reclaims the object's storage. Execution of the finalizer provides an opportunity to release resources such as open streams, files and network connections, whose resources may that might not otherwise be released automatically through the normal action of the garbage collector. In Java, the finalize()
method of java.lang.Object
is used for this purpose.
There are a sufficient number of caveats problems associated with the use of finalizers to only limit their use to exceptional conditions:
- There is no fixed time at which finalizers must be executed as this depends on the JVM. The only guarantee is that any finalizer method that executes will do so sometime after the associated object has become unreachable (detected during the first cycle of garbage collection), and sometime before the garbage collector reclaims the associated object's storage (during the garbage collector's second cycle). Execution of an object's finalizer may be delayed for an arbitrarily long time after the object becomes unreachable. Consequently, avoid implementing invoking time-critical functionality such as closing file handles in a finalizer in an object's
finalize()
method . For instance, closing file handles in a finalizer is not recommendedis problematic.
- The JVM may terminate without invoking the finalizer on some or all unreachable objects. Consequently, attempts to update critical persistent state from finalizer methods can fail without warning. Similarly, Java provides no guarantee that finalizers will execute on process termination. Methods such as
System.gc()
,System.runFinalization()
,System.runFinalizersOnExit()
andRuntime.runFinalizersOnExit()
either lack such guarantees or have been deprecated because of lack of safety and potential for deadlock.
...
- A programmer can unintentionally resurrect an object's reference in the
finalize()
method. When this occurs, the garbage collector must determine yet again whether the object is free to be deallocated. Further, because thefinalize()
method has executed once, the garbage collector cannot invoke it a second time.
- Do not use finalizers to release scarce resources as a side-effect of garbage collection. Garbage collection usually depends on memory availability and usage rather than on the scarcity of some other particular resource. Consequently, when memory is readily available, a scarce resource may be exhausted in spite of the presence of a finalizer that could release the scarce resource if it were executed. See guidelines FIO06-J. Ensure all resources are properly closed when they are no longer needed and TPS00-J. Use thread pools to enable graceful degradation of service during traffic bursts for more details on handling scarce resources correctly.
...
Wiki Markup |
---|
Joshua Bloch \[[Bloch 2008|AA. Bibliography#Bloch 08]\] suggests implementing a {{stop()}} method explicitly such that it leaves the class in an unusable state beyond its lifetime. A {{private}} field within the class can signal whether the class is unusable. All the class methods must check this field prior to operating on the class. This is akin to [the first exception|OBJ05-J. Prevent access to partially initialized objects#OBJ04-EX1] discussed in guideline [OBJ05-J. Prevent access to partially initialized objects]. As always, a good place to call the termination logic is in the {{finally}} block. |
Exceptions
MET18-EX1: Sometimes it is necessary to use finalizers especially EX0: Finalizers may be used when working with native code . This is because the garbage collector cannot re-claim memory used by code written in another language . Also, and because the lifetime of the object is often unknown. Again, the native process must not perform any critical jobs that require immediate resource deallocation.
In such cases, finalize()
may be used. Any subclass that overrides finalize()
must explicitly invoke the method for its superclass as well. There is no automatic chaining with finalize
. The correct way to handle this is shown below.
...
Wiki Markup |
---|
Alternatively, a more expensive solution is to declare an anonymous class so that the {{finalize()}} method is guaranteed to run for the superclass. This solution is applicable to {{public}} non-final classes. "The finalizer guardian object forces {{super.finalize}} to be called if a subclass overrides {{finalize()}} and does not explicitly call {{super.finalize}}". \[[JLS 2005|AA. Bibliography#JLS 05]\] |
...