The Java Finalize Method

The Java finalize method is a method of the Java Object class, that is inherited by all Java objects.

1
protected void finalize throws Throwable{}

The finalize method is called by the Garbage collector as part of its cleanup process. The idea of the finalize method is to give an object the opportunity to cleanup after itself such as closing resources to databases, Network resources etc.

However, it is recommended that the finalize method is not used, due to its unpredictability as we will discuss later in this tutorial. So please don’t use it in your applications.

Finalize Method In Action

As mentioned the finalize method gets invoked when the configured garbage collector executes its algorithm and locates an instance of an object that should be reclaimed. The finalize method is also commonly referred to as a finalizer.

Let’s look at an example of how to to use the finalize method in Java.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
public class FinalizeExample {
    private FileReader fr;

    public FinalizeExample() throws IOException {
        fr = new FileReader(ResourceUtils.getFileFromResources("file.txt"));
    }

    public void doSomethingWithFile() throws Exception {
        fr.read();
    }

    @Override
    public void finalize() {
        try {
            fr.close();
            System.out.println("Finalize method called");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

}

Above the FinalizeExample class creates an operating system file handle to read the file file.txt located on the resource path. As you can see the FinalizeExample class does not explicitly close the file handle by calling:

1
FileReader.close()

Instead we put this logic into the finalize method:

1
2
3
4
5
6
7
8
9
@Override
public void finalize() {
    try {
        fr.close();
        System.out.println("Finalize method called");
    } catch (IOException e) {
        e.printStackTrace();
    }
}

When the garbage collector cleans up an instance of the FinalizeExample class the finalize method should be called and the file handle should be closed thus, freeing up system resources.

However, there are some problems with relying on the finalize method to perform this task.

Problems With Finalize

There are a number of issues with using the finalize method. Firstly, the time when the garbage collector calls a finalizer is not deterministic. This could be dependent on the type of garbage collector that is configured with a particular version of the JVM, JVM configuration properties, or environment conditions that are outside the control of a programmer.

Therefore a garbage collection cycle can execute at a random interval that is outside of our control. Therefore, it is not a good idea to rely on the finalize method as resources can be kept opened / held for longer periods of time.

A request can be made to the garbage collector to perform a cycle by calling the method:

1
System.gc();

However, System.gc() is just a request to the garbage collector, and its up to the JVM when the garbage collector is invoked in response to this call.

1
2
3
4
5
6
@Test
public void finalizerTest() throws Exception {
    FinalizeExample finalizer = new FinalizeExample();
    finalizer.doSomethingWithFile();
    System.gc();
}

If the above call is executed you probably won’t see the finalize method executed in the FinalizeExample class due to the random nature of the garbage collector, and the conditions necessary for it to run.

It is important to note that calling System.gc() is a heavyweight operation that can degrade system performance, so it should not be called in production code. The decision of when garbage collection should run should be left to the discretion of the garbage collector, as it has the data to make the best decision for when it should run.

Finalize Method Important Points

Let’s review the important points regarding the Java finalize method.

  • There is no guarantee about the time when finalize is called, due to the nature of the garbage collector.
  • The finalize method should not be used as it can result in resources being kept alive longer than necessary, thus eating system resources.
  • Calling System.gc() is just a request to the JVM to indicate that you would like to perform garbage collection, it is still up to the JVM to decide when the garbage collector should run, such as being low on memory.
  • Calling System.gc() can degrade system performance so it should not be called in production code.
  • To see garbage collection in action you can attach a tool such as jconsole to force a garbage collection cycle.

Removing The Finalize Method

As we mentioned you should not use the finalize method due to its unpredictable execution. Lets refactor the code in the FinalizeExample class to remove the finalize method.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
public class FinalizeExampleRefactored {
    private FileReader fr;

    public FinalizeExampleRefactored() throws IOException {
        fr = new FileReader(ResourceUtils.getFileFromResources("file.txt"));
    }

    public void doSomethingWithFile() throws Exception {
        fr.read();
    }

    public void close() {
        try {
            fr.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

In the above code we replace the finalize method with a close method to close the file handle resource. This is the approach you should follow in your programs to always ensure that resources are closed when they are no longer required.

Conclusion

In this tutorial we examined the finalize method in Java. We mentioned that you should not use the finalize method in your own programs due to its unpredictable nature.

From Java 9 the finalize method is deprecated and will probably be removed in a future relase.