Java Language Finalization


Example

A Java object may declare a finalize method. This method is called just before Java releases the memory for the object. It will typically look like this:

public class MyClass {
  
    //Methods for the class

    @Override
    protected void finalize() throws Throwable {
        // Cleanup code
    }
}

However, there some important caveats on the behavior of Java finalization.

  • Java makes no guarantees about when a finalize() method will called.
  • Java does not even guarantee that a finalize() method will be called some time during the running application's lifetime.
  • The only thing that is guaranteed is that the method will be called before the object is deleted ... if the object is deleted.

The caveats above mean that it is a bad idea to rely on the finalize method to perform cleanup (or other) actions that must be performed in a timely fashion. Over reliance on finalization can lead to storage leaks, memory leaks and other problems.

In short, there are very few situation where finalization is actually a good solution.

Finalizers only run once

Normally, an object is deleted after it has been finalized. However, this doesn't happen all of the time. Consider the following example1:

public class CaptainJack {
    public static CaptainJack notDeadYet = null;

    protected void finalize() {
        // Resurrection!
        notDeadYet = this;
    }
}

When an instance of CaptainJack becomes unreachable and the garbage collector attempts to reclaim it, the finalize() method will assign a reference to the instance to the notDeadYet variable. That will make the instance reachable once more, and the garbage collector won't delete it.

Question: Is Captain Jack immortal?

Answer: No.

The catch is the JVM will only run a finalizer on an object once in its lifetime. If you assign null to notDeadYet causing a resurected instance to be unreachable once more, the garbage collector won't call finalize() on the object.

1 - See https://en.wikipedia.org/wiki/Jack_Harkness.