Sanku
Sanku

Reputation: 511

Java finalize() method is not called after using gc() method?

To see the working of finalize() method in java which is called when the object is about to be destroyed, I have wrote the following program

class counterTest{
    public static int count;
    public counterTest(){
        count++;
    }
}

public class finalize {

    public static void main(String args[]){

        counterTest obj1=new counterTest();
        System.out.println("Number of objects :" + counterTest.count);
        counterTest obj2=new counterTest();
        System.out.println("Number of objects :" + counterTest.count);
        Runtime rs=Runtime.getRuntime();
        obj1=null;
        obj2=null;
        rs.gc();
    }
    protected void finalize(){
        System.out.println("Program about to terminate");
        counterTest.count--;
        System.out.println("Number of objects :" + counterTest.count);
    }
}

I expected the output to be like this

Number of objects :1 
Number of objects :2 
Program about to terminate 
Number of objects :1 
Program about to terminate 
Number of objects :0

But I am just getting the first two lines. Since I am making the objects references to null and then calling the gc() method, I expect that the statements written in inside finalize() method should be displayed. Does this mean there is no guarantee that finalize() method will be called each time we have used gc() method.

Upvotes: 3

Views: 344

Answers (2)

Alexander Petrov
Alexander Petrov

Reputation: 9492

Your finalize method should be in the counterTest and then it will "maybe" be invoked. You never really create and instance of the "finalize" class. Therefore your finalize method never have the chance to be executed.

Here is updated code that should work as you expect:

class counterTest{
    public static int count;
    public counterTest(){
        count++;
    }

    protected void finalize(){
        System.out.println("Program about to terminate");
        counterTest.count--;
        System.out.println("Number of objects :" + counterTest.count);
    }
}

public class Finalize {

    public static void main(String args[]){

        counterTest obj1=new counterTest();
        System.out.println("Number of objects :" + counterTest.count);
        counterTest obj2=new counterTest();
        System.out.println("Number of objects :" + counterTest.count);
        Runtime rs=Runtime.getRuntime();
        obj1=null;
        obj2=null;
        rs.gc();
    }

}

It should be noted that the "finalize" methods are not meant to be overridden because they are unreliable. You never know when the Garbage collector will collect a particular object so relaying on it to close your database connections or doing other similar stuff is a No, no, no...

Upvotes: 2

hyde
hyde

Reputation: 62797

First of all, you code does not have an instance (AKA object) of finalize class. main method is static and does not have an instance.

But even if you did have an instance, in Java GC and calling finalize() methods is not very deterministic or guaranteed. It's not a destructor similar to C++. So even if you added finalize() method to counterTest class, of which you create some instances, there's no guarantee it'll get called.

If you want similar behavior as you would have with a destructor, you need to design your code around try-with-resources pattern. Then AutoCloseable interface's close() method takes the role of destructor.

PS. There is a very strong convention in Java to use so called Pascal case with class names, so your classes should be named CounterTest and Finalize.

Upvotes: 2

Related Questions