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
_ _____ _ <br />Used to be a Java Programmer but now I work on Microsoft Technologies - Word, Excel and Outlook!
Joined: May 30, 2003
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
But an object can be resurrected in the finalize method. When it does get resurrected, and then GC'd later on, the finalize method will NOT be called again. So now the question is why?
Hi Alton, I do not know the answer to your question. None of my garbage collection sources explain why. Would you mind if I speculate? Since the specification guarantees that a finalizer is run at most one time per object, we are guaranteed that an object will not be continually resurrected.
Well, an object can be resurrected many times! IMHO the finalize() method shouldn't be used at all. If the GC made any guarantees at all about when it would run then maybe I'd change my opinion, but given that you can NEVER be sure if the GC will run, the finalize() method has little use. That said, *my* speculation is that because the benefit is small, and the lifecycle issues concerning 'reachable', 'unfinalized', 'finalizable', blah, blah, blah is very complex, Sun choose a simple approach.
Spot false dilemmas now, ask me how!
(If you're not on the edge, you're taking up too much room.)
Joined: May 30, 2003
Thank you all. I asked that question because it has been said that one of the use of the finalize() method is for an object cleanup. I find it stranged that if an object is resurrected, you cannot do another cleanup on that object. Pehaps Bert is right. The finalize() method should not be relied upon. [ July 29, 2003: Message edited by: Alton Hernandez ]
I think that when finalize() was originally designed, they were thinking of it much like a destructorin C++, and they maybe wanted to ensure that an object wasn't "destroyed" twice. It seems like an odd rule now. But the assurance that it's only called once is occasionally useful. For example if you want to monitor when objects are being collected, you can get some info about this by putting System.out.println("I'm dying here"); in the finalize(). This doesn't exactly tells you when the object is collected, but if the message is seen it tells you the object was previously identified as eiligible for collection, and if you didn't actually resurrect it in the finalizer you can assume that the object is on its way out now. (Unless maybe someone has a WeakReference to it; I don't remember the sequence there.) Anyway, if the JVM were allowed to call the finalizer twice that could undermine your ability to monitor collection in this manner. At least, it would lead to confusing results. 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.) Bottom line though, I agree with those saying finalizers are unreliable for most applications. I think if they were redisigning Java from scratch today, they probably would omit finalizers entirely. But we're stuck with them - best thing is usually to ingore them and pretend they're not there.
Bert, How can objects be resurrected from GC death multiple times if the GC only runs finalize once? The only way I can think of that might work is that let's say we had 4 objects, each with a reference to another of the 4 in a round-robin...thus, when all references to those 4 are broken off (other than amongst themselves), the kiss of death has been cast upon them...that means up to 4 finalizes can occur...and if they each have the reference to each other (or to at least one of the other three), they can "save" the objects....4 times. Once for each finalize. Is there another way or methodology that would conceivably (or actually) allow an infinite number of resurrections? Ross
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.)
If all above functions are critical, they should not be in finalize() as finalize itself is not guarranteed to run. You might not get correct count or a resource might never close. However, Bruce Eckel sites following use for finalize:
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
Ron, I think your use of finalize, as a safety net in case the programmer forgot to call the clean-up method, is also acceptable. Maybe the people writing the finalize method just thought that the clean up tasks should not be repeated.
SCJP2. Please Indent your code using UBB Code
Joined: Jan 30, 2000
If all above functions are critical, they should not be in finalize() as finalize itself is not guarranteed to run. You might not get correct count or a resource might never close. Absolutely - you can't guarantee that finalize() will ever run. Well, you can guarantee that if an object was ever completely collected, then finalize did run. But this isn't very useful since you can never guarantee that complete collection occurred. So, never depend on finalize occurring. If code is critical, you should guarantee that it runs without finalize(). However I agree with Ron and Jose that it may be helpful to provide added security by putting code in a finalizer in addition to putting it elsewhere. We really should not need the finalizer code, but if someone makes a mistake, it can add an extra level of security. It's never a guarantee that your code will work as planned, but it may increase your chances of avoiding some errors. The rest of this is really outside the scope of Programmer Certification, so many people should just skip it if they're just here for certification. (And if this particular line of conversation continues we should probably more it somewhere else.) But for those who are interested: There are however a couple problems I see with this approach. One is that even though they're supposed to try to guarantee that (for example) close() is called on an object, without relying on finalize, programmers may nonetheless come to expect that finalize() will fix their mistakes, and thus, they come to rely on finalize(), which they should not. Furthermore fixing things quietly with finalize() may make it harder to detect programming errors when they occur. Someone may neglect to call close(), but most of the time, the error is repaired by finalize() - so it becomes harder to reproduce the problem when it does occur. So, my preferred approach is something like this:
The other concern is that with modern generational garbage collection, a class having any finalize() method (other than the one inherited from Object()) can decrease the effectiveness of garbace collection - sometimes significantly. This is especially true if the object is being created inside a loop, such that each new object should be eligible for GC at the end if each loop iteration. Generational GCis really good at cleaning this stuff up quickly, but putting a finalize() method on such an object makes the task of GC more complex, and generational GC is not optimized for finalizable objects - they tend to live on the heap a long time after they were eligible for GC. So, if memory usage is an issue, finalize() may be a bad idea in general. I would recommend using finalize() as I showed above during testing, and if memory turns out to be an issue, try commenting out the finalize() to see if it helps. [ July 30, 2003: Message edited by: Jim Yingst ]