Let's say I have created some resource class with a close() method for cleaning up the resource, and I want to override finalize() to free the resource (and print a warning) if someone has forgotten to call close(). How can this be done properly?
Note: I know that using finalize() is usually bad idea, and that it's not guaranteed to be called, there are several other questions discussing this. This question is specifically about how to implement a finalizer in Java, not about why you should (or shouldn't).
Overview. Finalize method in Java is an Object Class method that is used to perform cleanup activity before destroying any object. It is called by Garbage collector before destroying the object from memory. Finalize() method is called by default for every object before its deletion.
In computer science, a resource leak is a particular type of resource consumption by a computer program where the program does not release resources it has acquired. This condition is normally the result of a bug in a program.
The Finalize method is used to perform cleanup operations on unmanaged resources held by the current object before the object is destroyed. The method is protected and therefore is accessible only through this class or through a derived class.
It is invoked only once during the execution of a program. Following are some notable points about the finalize method. Since this method belongs the Object class, which is the super class of all the classes in java, you can override it from any class.
In effective java (2nd edition), Joshua goes in detail in Item #7 about how you can do this. He first suggests that you should almost never use finalizer
s. However, one reason to use it to only print a log statement saying you have a resource leak. He says one of the draw backs to doing it this way is that someone can extend your class and not properly call the super finalizer. So he suggests to do something like this in the subclass:
// Manual finalizer chaining
@Override protected void finalize() throws Throwable {
try {
... // Finalize subclass state
} finally {
super.finalize();
}
}
This is to ensure that if something breaks in the current class the finally
will still get called. This maybe a bad solution because it depends on the person who is subclassing your class. An alternate solution is to use a guardian object file to get this done. This looks like:
// Finalizer Guardian idiom
public class Foo {
// Sole purpose of this object is to finalize outer Foo object
private final Object finalizerGuardian = new Object() {
@Override protected void finalize() throws Throwable {
... // Finalize outer Foo object
}
};
... // Remainder omitted
}
This is a cleaner approach because you know that no one can override that functionality.
The suggested way to closing resources is still implementing Closeable
and make sure it is up to the user to close. As Josuha suggests, you shouldn't do any time sensitive operations in the finalize
method. The JVM may choose to run it as sometime in the future. If you are depending on this method to do commits or something important then that is a bad idea.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With