Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to properly implement a finalizer for detecting resource leaks in Java

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?

  • Is it recommended only for native (JNI-allocated) resources?
  • What happens if you use a reference to another object that has been finalized, from a finalizer? If there are cyclic dependencies I don't see how the garbage collector can prevent you from accessing objects whose finalizers could have been executed.
  • Are there any better alternatives to overriding finalize() for detecting and/or dealing with resource leaks?
  • Any other pitfalls to be aware of when implementing a finalizer?

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).

like image 235
Soulman Avatar asked Sep 17 '12 14:09

Soulman


People also ask

What is finalizer method in Java?

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.

What is resource leak in Java?

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.

What is finalizer method?

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.

Can we invoke finalize method in Java?

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.


1 Answers

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 finalizers. 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.

like image 71
Amir Raminfar Avatar answered Sep 20 '22 15:09

Amir Raminfar