aspose file tools*
The moose likes Beginning Java and the fly likes Destructor Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login
JavaRanch » Java Forums » Java » Beginning Java
Bookmark "Destructor" Watch "Destructor" New topic
Author

Destructor

Jay Will
Greenhorn

Joined: Feb 18, 2003
Posts: 2
Does Java have a destructor that is called after garbage collection?
Dmitry Melnik
Ranch Hand

Joined: Dec 18, 2003
Posts: 328
protected void finalize() throws Throwable
Dirk Schreckmann
Sheriff

Joined: Dec 10, 2001
Posts: 7023
Welcome to JavaRanch, Jay!

You might like to take a look at the Object class documentation, which includes the documentation for the aforementioned finalize method.


[How To Ask Good Questions] [JavaRanch FAQ Wiki] [JavaRanch Radio]
Ilja Preuss
author
Sheriff

Joined: Jul 11, 2001
Posts: 14112
Notice that

- it is called *before* an object gets gc'ed, not after, and
- it is *not* guaranteed to be called at all, as an object may not get gc'ed

Therefore it's not really like a destructor.


The soul is dyed the color of its thoughts. Think only on those things that are in line with your principles and can bear the light of day. The content of your character is your choice. Day by day, what you do is who you become. Your integrity is your destiny - it is the light that guides your way. - Heraclitus
sever oon
Ranch Hand

Joined: Feb 08, 2004
Posts: 268
Ilja's right.

The process of gc'ing an object is the destruction of that object and the reclamation of all of the memory used by said object.

A C++-style destructor, in fact, does more than simply destroy the object by freeing the memory used by it (though it does indeed do that). It provides a place for developers to free other resources that may be held open by the object, such as file handles in the operating system. Since destruction of objects in Java is automated by the gc, there is no opportunity for developers to run this kind of code as part of the destruction process itself.

Or, rather, there would be no way if not for the finalize() method. finalize() is a method provided on java.lang.Object, the granddaddy of all objects, and may be overridden for precisely this purpose. Anything provided in the body of the finalize() method is carried out before gc because the garbage collector runs it before destroying the object. Usually, though, it is advisable to avoid using the finalize() method because there are some subtleties and performance problems with doing so.

Performance-wise, finalize() is a bad idea because of the way most JVMs work. The gc organizes objects in memory into groupings based on how many references there are to those objects. Whenever the gc runs it analyzes those groupings and updates them according to what's happened since the last gc pass. Typically, even after the last reference to an object disappears, it takes several passes for the gc to recognize that and move it to the "ready for collection" grouping. Just before collection, the gc checks to see if there's a finalize() method present, and if so it runs it...but at that moment, all bets are off. The gc knows that the finalize() method itself may have caused several references to the object to be handed out all over town and now the object is no longer valid for gc, so it goes to the back of the line again. Finalizers are guaranteed only to be run once (I believe), so the next time it makes its way up to the head of the line, the gc will consider it as not having a finalize() method and it will get collected this time.

You can see, though, if you have even one class with a finalizer that has a significant number of instances floating around, it causes the gc workload to more than double for those objects. Since garbage collection is historically the feature that causes the most performance problems, this can be an issue. Also, many developers don't understand that there's no guarantee an object will be formally collected by the gc. In most applications that exit, there are still objects hanging around that have not yet been gc'd, and in that case the JVM will typically just exit and close. If your finalize() method had any important work yet unperformed (updating a log file, closing a file handle, closing a socket connection), then it will be left open and it will then become dependent upon the operating system to clean up these unclosed resources. Most of the modern desktop OSes are smart enough to do this (with a significant performance penalty), but that's not the point--there are a lot of real time or embedded system OSes that don't. In other words, if your finalizer must run, then you're depending on particular OS features to be present and you're no longer writing platform-independent, 100% Sun-certified Java anymore.

So, what's the proper way to handle this? Do what Sun does...provide a cleanup method and make it the responsibility of the caller using the object to properly dispose of it when done. java.net.Socket, for instance, has a close() method that the caller is expected to call when done using the socket connection. Ugly? Maybe. Elegant? Perhaps not (but perhaps--a strong argument can be made that this is simply a behavior that ought to be requested by the caller just like any other behavior of that class). Necessary? Yup.

sev

[ August 24, 2004: Message edited by: sever oon ]
[ August 24, 2004: Message edited by: sever oon ]
 
I agree. Here's the link: http://aspose.com/file-tools
 
subject: Destructor