Thursday, 16 July 2015

finalize method in Java

There may be a situation when an object will need to perform some action just before it is getting garbage collected. For example if an object is holding some non-java resources like file handle then it is better to make sure that these resources are closed before an object is destroyed because simply reclaiming the memory used by an object would not guarantee that the resources it held would be reclaimed.
For that purpose Java provides a mechanism called finalization through finalize() method. In finalize method we can provide the actions to release the resources before the object is destroyed.

When is finalize() method called

As we know that in Java object memory deallocation happens automatically through garbage collection. In Java, garbage collector is run by the run time environment periodically and it looks for the objects for which there are no existing references. finalize method for an object is executed just before it is garbage collected. But here lies the caveat According to Java language specification - http://docs.oracle.com/javase/specs/jls/se7/html/jls-12.html#jls-12.6 The Java programming language does not specify how soon a finalizer will be invoked that's one reason why we should not rely solely on finalize() method to release resources.

According to Joshua Bloch in his book Effective Java, Item 7: Avoid Finalizers
"The promptness with which finalizers are executed is primarily a function of the garbage collection algorithm, which varies widely from JVM implementation to JVM implementation. The behavior of a program that depends on the promptness of finalizer execution may likewise vary. It is entirely possible that such a program will run perfectly on the JVM on which you test it and then fail miserably on the JVM favored by your most important customer."

General form of finalize method

finalize method is provided as a protected method in the Object class.

protected void finalize() throws Throwable

Just as a reminder the protected access modifier provides the access as - Variables, methods and constructors which are declared protected in a superclass can be accessed only by the subclasses in other package or any class within the package of the protected members' class.
Since all the classes have Object class as the super class either directly or indirectly so this method would be accessible to each and every class anyway so it makes sense to keep the access as protected.

How to use finalize method

The finalize method of class Object performs no special action; it simply returns normally. Any class which needs some functionality to be provided in finalize() method has to override this definition and provide the functionality. According to Java docs - The finalize method may take any action, including making this object available again to other threads; the usual purpose of finalize, however, is to perform cleanup actions before the object is irrevocably discarded.

How to properly write a finalize() method

Like constructor chaining in Java there is no finalizer chaining so super class finalize method would not be called automatically. As example If there is class A which provides a finalize method, if Class A is extended by class B and class B overrides the finalize method then only Class B's finalize method will be called. Class A's finalize method would not be called automatically. Thus we need to explicitly call it using super -

protected void finalize() throws Throwable {
     try {
         // clean up
     } finally {
         super.finalize(); // call parent class’ finalize
     }
}

Example code for finalize method

Here is a simple example where I have created an object then set that object reference as null. Also called System.gc() to run garbage collector. Note you may not get the output in some of the runs as System.gc() is also more of a suggestion to the virtual machine to reclaim memory from unused objects it may not run as soon as System.gc() is called and the program may terminate not at all calling the finalize method.

public class FinalizeDemo {
    int i;
    FinalizeDemo(int num){
        this.i = num;
    }
    public static void main(String[] args) {
        // creating object
        FinalizeDemo finalizeDemo = new FinalizeDemo(10);
        Temp temp = new Temp();
        // setting object reference as null so it is 
        // eligible for garabge collection
        finalizeDemo = null;
        temp.doCalcualtion();
        // setting object reference as null so it is 
        // eligible for garabge collection
        temp = null;
        // Calling System.gc() to run garbage collector
        System.gc();        
    }
    
    @Override
    protected void finalize() throws Throwable {
        try{
            System.out.println("finalize method called for FinalizeDemo");
        }finally{        
            super.finalize();
        }
    }
    
}

class Temp{    
    public void doCalcualtion(){
        int i = 5;
        System.out.println("value of i is " + i);
    }
    @Override
    protected void finalize() throws Throwable {
        try{
            System.out.println("finalize method called for Temp");
        }finally{
            super.finalize();
        }
    }
}

Output

value of i is 5
finalize method called for Temp
finalize method called for FinalizeDemo

Though I have used System.gc here to some how make sure that finalize() method is indeed called but don't rely on it. To quote Joshua Bloch again "Don't be seduced by the methods System.gc and System.runFinalization. They may increase the odds of finalizers getting executed, but they don't guarantee it. The only methods that claim to guarantee finalization are System.runFinalizersOnExit and its evil twin, Runtime.runFinalizersOnExit. These methods are fatally flawed and have been deprecated."

When we can use finalize method

Though there are other better alternatives to clean up resources like a finally block or try-with-resources(ARM) available from Java 7. But to make sure, just as an extra safety measure, that resources are indeed closed before the object is destroyed finalize() method may be used. But be forewarned it does comes with a hit on performance.

Finalize method and exception handling

Any exception thrown by the finalize method while finalize method is executing causes the finalization of this object to be halted, but is otherwise ignored.

Points to Note

  1. Every class inherits the finalize() method from java.lang.Object.
  2. The finalize method is called by the garbage collector when it determines no more references to the object exist
  3. The finalize method of class Object performs no special action; it simply returns normally. Subclasses of Object may override this definition.
  4. If overridding finalize() it is a good programming practice to use a try-catch-finally statement and to always call super.finalize() as there is no concept of finalizer chaining.
  5. The finalize method is never invoked more than once by a Java virtual machine for any given object.

That's all for this topic finalize method in Java. If you have any doubt or any suggestions to make please drop a comment. Thanks!


Related Topics

  1. finally block in Java
  2. final in Java
  3. final Vs finally Vs finalize
  4. Constructor chaining in Java
  5. Core Java basics interview questions

You may also like -

>>>Go to Java Basics page

No comments:

Post a Comment