3

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.

Vladimir Vagaytsev
  • 2,871
  • 9
  • 33
  • 36
Sai Sankalp
  • 451
  • 1
  • 4
  • 14
  • 3
    Calling gc does not guarantee finalize execution, but it just suggests. – gevorg Jul 17 '16 at 10:49
  • 2
    @Sai Have a look to [java code convention](http://www.oracle.com/technetwork/java/codeconventions-150003.pdf). – catch23 Jul 17 '16 at 10:50
  • Possible duplicate of [How to force garbage collection in Java?](http://stackoverflow.com/questions/1481178/how-to-force-garbage-collection-in-java) – gevorg Jul 17 '16 at 10:52
  • Have a look at **J. Bloch's "Effective Java" 2nd edition, Item 7, p.27**, it gives good explanations on finalizers – Vladimir Vagaytsev Jul 17 '16 at 11:48

2 Answers2

2

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...

Alexander Petrov
  • 9,204
  • 31
  • 70
  • Thank you its working now.But why is that the finalize() method should be in the class for which we have created the objects.I mean if we have 10 classes,then is it necessary to have 10 finalize() methods in each class? – Sai Sankalp Jul 17 '16 at 10:50
  • 1
    It *may* be invoked. There is nothing that guarantees GC will be invoked, let alone finalisation. – user207421 Jul 17 '16 at 10:51
  • 1
    @SaiSankalp That does not make sense. *One* `finalize()` method per class. – user207421 Jul 17 '16 at 10:52
  • @EJP that's what I was thinking.So we can't guarantee that gc() gets evoked every time we have kept the object references to null am I right? – Sai Sankalp Jul 17 '16 at 10:54
  • @Sai finalize() methods in Java are "in practice" never really used to do anything. It is mostly the garbage collector that is using them. Nobody expects that you will override 10 finalize methods in 10 different classes. Most of the times I have see in my career someone override finalize() it is always an error. – Alexander Petrov Jul 17 '16 at 10:54
  • @AlexanderPetrov My answer also has a single mystery downvote. I guess there's someone who desn't like the question... – hyde Jul 17 '16 at 11:05
  • @hyde one old user on the forum once told me that it is usually pointless to ask this question "Why?", as you mostly never receive answer. I kind of agree with it , but when I think I have right, it is always a bit frustrating :) – Alexander Petrov Jul 17 '16 at 11:16
2

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.

hyde
  • 60,639
  • 21
  • 115
  • 176