Finalize

This lesson talks about the finalize method of the Object class.

Question # 1

Explain the finalize() method?

The finalize() method is a protected and non-static method of the java.lang.Object class and is also sometimes called the finalizer. The finalize() method is invoked by the JVM when an object is garbage collected. A user can override the finalize() in his class to dispose of system resources or to perform cleanup tasks.

Example use of finalize

class MyWeirdInputStreamReaderClass {

    BufferedInputStream bis = null;

    void someReadInputMethod() throws FileNotFoundException {
        BufferedInputStream bis = new BufferedInputStream(new FileInputStream("pathToFile"));
        // ... logic to initialize bis variable but user
        // doesn't close the stream
    }

    // Don't use finalize in production code, bad idea!
    @Override
    protected void finalize() {
        try {
            bis.close();
        } catch (IOException io) {
            // ... log a message
        }
    }
}

Question # 2

Why should finalize not be used?

There are several reasons to not override the finalize() method which are listed below:

  • It is not possible to predict when the garbage collector will invoke the finalize() method or if the garbage collector will even run before your Java program exits. Therefore, if you have any resource cleanup code in the finalize() method, it may not be invoked at all or in time to free-up resources and may cause a program crash.

  • Using finalize() may affect portability of a program as garbage collection algorithms are JVM implementation dependent and the same program may perform well on one system and not as well on another.

  • Performance may be negatively impacted when using finalizers as JVM executes more number of operations when constructing and destroying objects with non-empty finalizers.

  • If a finalizer throws an exception, the finalization process is canceled, and the exception is ignored, leaving the object in a corrupted state without any notification.

Question # 3

What the alternatives to finalizing objects?

Some possibilities to finalizing objects are:

  • The try-with-resources idiom can be used to clean up objects. This requires implementing the AutoCloseable interface.

  • Using a PhantomReference to perform cleanup when object is garbage collected

  • Using Cleaner class to perform cleanup actions.

  • Implement a close() method, which does the cleanup and document that the method be called.

Question # 4

Explain object resurrection?

When the JVM's Garbage Collector is eventually about to remove an unused object, the object's finalize() method is invoked. But, if we re-create a reference to the object again in the object's own finalize() method, the object becomes live again. The about to be garbage collected object, now suddenly has a reference to it and the JVM will refrain from removing it. Metaphorically, the object has been resurrected from death

Below, is a sample program that resurrects dead objects.

Class with objects that get resurrected

class UsefulObjectClass {

    HashSet<UsefulObjectClass> immortals;

    public UsefulObjectClass(HashSet<UsefulObjectClass> immortals) {
        this.immortals = immortals;
    }

    @Override
    public void finalize() {
        System.out.println("I am being finalized.");
        immortals.add(this);
    }

    public void printName() {
        System.out.println("Hi, I am a useful object.");
    }
}

We can create objects of the the above class UsefulObjectClass and they'll not be garbage collected in the following example snippet:

    // Global variable
    static HashSet<UsefulObjectClass> immortals = new HashSet<>();

    UsefulObjectClass obj = new UsefulObjectClass(immortals);
import java.util.HashSet;
class Demonstration {
static HashSet<UsefulObjectClass> immortals = new HashSet<>();
public static void main( String args[] ) throws InterruptedException {
UsefulObjectClass obj = new UsefulObjectClass(immortals);
obj.printName();
obj = null;
Runtime.getRuntime().gc();
// Sleep the main thread so that the garbage collector thread performs finalization
Thread.sleep(1000);
if (immortals.size() == 1) {
System.out.println("Useful object saved from garbage collection.");
}
System.out.println("exiting");
}
}
class UsefulObjectClass {
HashSet<UsefulObjectClass> immortals;
public UsefulObjectClass(HashSet<UsefulObjectClass> immortals) {
this.immortals = immortals;
}
@Override
public void finalize() {
System.out.println("I am being finalized.");
immortals.add(this);
}
public void printName() {
System.out.println("Hi, I am a useful object.");
}
}

Question # 5

How many times does JVM invoke the finalize() method on an object?

Java invokes the finalizer on an object at most one time. Even if the object is resurrected in the finalize method, it'll not have finalize invoked on it the next time it becomes garbage eligible.

Note

With the release of JDK 9 finalize() has been deprecated. Deprecation does not necessarily mean removal or future removal. It is an indication used to note that the annotated element should (if possible) be avoided and may potentially be removed in future releases of the Java platform.