From the API doc:
The finalize method is never invoked more than once by a Java virtual machine for any given object.
Originally posted by Bishal P:
The finalize method is invoked by the Garbage Collector when it has determined that an object is no longer used and can be garbage collected. Since one object can be garbage collected only once, the finalize method will also be invoked only once
For more information check out the API
You might want to do other things in finalize() which should only be performed once - e.g. you could decrement a count of living objects, or invoke the close() method on some other resource that can only be closed once. (Though most close() methods are written so that a second close() simply has no effect.)
What is finalize( ) for?
So, if you should not use finalize( ) as a general-purpose cleanup method, what good is it? Feedback
A third point to remember is:
3. Garbage collection is only about memory.
That is, the sole reason for the existence of the garbage collector is to recover memory that your program is no longer using. So any activity that is associated with garbage collection, most notably your finalize( ) method, must also be only about memory and its deallocation. Feedback
Does this mean that if your object contains other objects, finalize( ) should explicitly release those objects? Well, no�the garbage collector takes care of the release of all object memory regardless of how the object is created. It turns out that the need for finalize( ) is limited to special cases in which your object can allocate some storage in some way other than creating an object. But, you might observe, everything in Java is an object, so how can this be? Feedback
It would seem that finalize( ) is in place because of the possibility that you�ll do something C-like by allocating memory using a mechanism other than the normal one in Java. This can happen primarily through native methods, which are a way to call non-Java code from Java. (Native methods are covered in Appendix B in the electronic 2nd edition of this book, available on this book�s CD ROM and at www.BruceEckel.com.) C and C++ are the only languages currently supported by native methods, but since they can call subprograms in other languages, you can effectively call anything. Inside the non-Java code, C�s malloc( ) family of functions might be called to allocate storage, and unless you call free( ), that storage will not be released, causing a memory leak. Of course, free( ) is a C and C++ function, so you�d need to call it in a native method inside your finalize( ). Feedback
After reading this, you probably get the idea that you won�t use finalize( ) much. You�re correct; it is not the appropriate place for normal cleanup to occur. So where should normal cleanup be performed? Feedback
You must perform cleanup
To clean up an object, the user of that object must call a cleanup method at the point the cleanup is desired. This sounds pretty straightforward, but it collides a bit with the C++ concept of the destructor. In C++, all objects are destroyed. Or rather, all objects should be destroyed. If the C++ object is created as a local (i.e., on the stack�not possible in Java), then the destruction happens at the closing curly brace of the scope in which the object was created. If the object was created using new (like in Java), the destructor is called when the programmer calls the C++ operator delete (which doesn�t exist in Java). If the C++ programmer forgets to call delete, the destructor is never called, and you have a memory leak, plus the other parts of the object never get cleaned up. This kind of bug can be very difficult to track down, and is one of the compelling reasons to move from C++ to Java. Feedback