Skip to main content

Blarg#27: Don't use finalize() as your only teardown method.

Posted by jfalkner on July 31, 2007 at 4:17 PM PDT

In short, don't rely on the finalize() method as your only cleanup method, especially if it is deleting files. Instead make up a cleanup method (cleanup() works nicely) that lazy deletes things. Here is an example.

public class Example {
  boolean isCleanedUp = false;
 
  public synchronized void cleanup() {
    if (isCleanedUp) return;
    // flag as cleaned up
    isCleanedUp = true;
    // put your clean up code here.
    // delete files, close DB connections, etc.
  }

  public void finalize() {
    cleanup();
    super.finalize();
  }
}

Wait...why do the above if the garbage collector will always call finalize before freeing up memory associated with an object? The reason is because the garbage collector doesn't always get a chance to clean up objects before the JVM terminates. This can be problematic, particularly in cases where you've made a temporary file or a socket connection that needs to be properly cleaned up.

By using an explicit cleanup() method as shown above you have an explicit method for cleaning up resources associated with an object the moment you are done using the object. Additionally, the boolean flag protects your code from accidentally trying to clean up the resource twice. The term "lazy delete" is used loosely because this approach is like lazy loading. The delete will occur only once and only when the code actually needs to do it.

Do note that the cleanup() method also nicely works in a try-finally block.

Example example = null;
try {
  example = new Example();
  //  do whatever logic you need to
}
finally {
  example.cleanup();
}

And one last trick copied from Bruce Eckel. If you are worried that portions of your code aren't cleaning up resources properly, simply tweak the finalize() method to check the isCleanedUp boolean and report finalize() calls that occur before any explicit call to cleanup().

Related Topics >>