Tuesday, August 7, 2007

Java finalize()

For any given object, finalize() will be called only once by the garbage collector.
Calling finalize() can actually result in saving an object from deletion.

Any exception thrown by finalize() during garbage collection halts the finalization but is otherwise ignored
finalize() is never run more than once on any object

In the finalize() method you could write code that passes a reference to the object in question back to another object, effectively uneligiblizing the object for garbage collection. If at some point later on this same object becomes eligible for garbage collection again, the garbage collector can still process this object and delete it. The garbage collector, however,will remember that, for this object, finalize() already ran, and it will not run finalize() again.

One reasonable, though rare, application for a finalizer is to free memory allocated by native methods. If an object invokes a native method that allocates memory (perhaps a C function that calls malloc()), that object's finalizer could invoke a native method that frees that memory (calls free()). In this situation, you would be using the finalizer to free up memory allocated on behalf of an object -- memory that will not be automatically reclaimed by the garbage collector.

Another, more common, use of finalizers is to provide a fallback mechanism for releasing non-memory finite resources such as file handles or sockets. As mentioned previously, you shouldn't rely on finalizers for releasing finite non-memory resources. Instead, you should provide a method that will release the resource. But you may also wish to include a finalizer that checks to make sure the resource has already been released, and if it hasn't, that goes ahead and releases it. Such a finalizer guards against (and hopefully will not encourage) sloppy use of your class. If a client programmer forgets to invoke the method you provided to release the resource, the finalizer will release the resource if the object is ever garbage collected.

If you feel you simply must bring an object back to life, consider cloning a new copy of the object instead of resurrecting the same old object. The reasoning behind this piece of advice is that garbage collectors in the JVM invoke the finalize() method of an object only once. If that object is resurrected and becomes available for garbage collection a second time, the object's finalize() method will not be invoked again.

Invoking superclass finalizers is good practice in any finalizer, even in cases where no superclass exists other than Object. The JVM does not automatically invoke superclass finalizers, so you must do so explicitly.

The most important point to take away from this article is that if a Java object needs to take some action at the end of its life, no automatic way exists in Java that will guarantee that action is taken in a timely manner. You can't rely on finalizers to take the action, at least not in a timely way. You will need to provide a method that performs the action and encourage client programmers to invoke the method when the object is no longer needed.

This article contained several guidelines that pertain to finalizers:
Don't design your Java programs such that correctness depends on "timely" finalization

Don't assume that a finalizer will be run by any particular thread

Don't assume that finalizers will be run in any particular order

Avoid designs that require finalizers to resurrect objects; if you must use resurrection, prefer cloning over straight resurrection

Remember that exceptions thrown by finalizers are ignored

If your program includes objects with finalizers that absolutely must be run before the program exits, invoke runFinalizersOnExit(true) in class Runtime or System

Unless you are writing the finalizer for class Object, always invoke super.finalize() at the end of your finalizers

More information can be obtained from the following link :

No comments: