Why is finalize not being called?

14,731

Solution 1

There is a lot to finalize() method which is frankly a lot to write, but in short:

An object is in the finalized state if it is still unreachable after its finalize method, if any, has been run. A finalized object is awaiting deallocation. Note that the VM implementation controls when the finalizer is run. You are almost always better off doing your own cleanup instead of relying on a finalizer. Using a finalizer can also leave behind critical resources that won't be recovered for an indeterminate amount of time.

In your case the reason it does not print is that you do not know when the finalizer thread will call the finalize() method. What is happening is that the program is terminating before anything can get printed. To check it: edit the code inside main code by( NOTE: this does not guarrantee nor should you should ever rely on it but still it does prints some time)

for(int i =0;i<1000000;i++)
    {
        MultipleConstruct construct = new MultipleConstruct(3);
        construct = null;
    }

There are a lot of disadvantages of using a finalize() right from taking more time in object construction to possibility of memory leakage and memory starvation. If you strongly refer to the same object inside the finalize() then it is never called the second time and thus can leave system in undesired state etc etc etc... The only place where you should use finalize() is as a safety net to dispose any resources like InputStream uses it to close (which again there is no guarrantee that it will will br run when your program is still alive). Another place to use it is while using natives where garbage collector has no control.

For more info visit:

http://jatinpuri.com/?p=106

Solution 2

q1) finalize method is called when the object is being garbage collected, thus, if no GC is being performed, your finalizer may not be called. You need to call super simply to preserve the behavior provided by Object implementation.

q2) the exact moment in which GC is performed depends on a lot of factors like: which JVM you are using, tuning parameters, amount of free heap, etc. So it does not only rely on a used heap threshold. You can also ask for a GC to be performed through System.gc() but you have no guarantee about if and when it will be actually executed. You can find some details on how to configure GC in http://java.sun.com/performance/reference/whitepapers/tuning.html

Solution 3

it gets called eventually or not at all

basically the GC scans the heap for everything that is not reachable and runs the finalizer on those (after which it needs to prove again it is not reachable for it to be freed)

however it can take a while (effectively undefined and actually dependent on program behavior) for the GC to find it which is why you shouldn't really rely on it to dispose of critical data

edit: as for circular references it distinguishes between objects with a finalize method and objects without one

for an object to be freed (deleted from main memory) it may not be reachable by any code (this includes finalizers that still need to run)

when 2 objects with finalizers are eligible to get the finalizers run the GC arbitrarily selects one object and runs the finalizer on it and then it can run the other object

note that a finalizer can run while the fields of the objects may or may not be finalized already

Share:
14,731

Related videos on Youtube

prap19
Author by

prap19

I am software developer working for Salesforce.com and a computer science graduate from Stony Brook University. I am an intermediate java programmer interested in data structures and algorithms. I love troll comics.

Updated on June 04, 2022

Comments

  • prap19
    prap19 almost 2 years

    I have couple of questions regarding garbage collector in java.

    Q1.As far as I understand, finalize() gets called when object is out of scope and JVM is about to collect garbage. I thought finalize() method is called automatically by garbage collector, but it does not seems to work in this case. What is the explanation? Why is the need for me to explicitly call finalize() method?

    public class MultipleConstruct {
        int x,y;    
        public MultipleConstruct(int x)
        {
            this.x= x;
            y=5;        
            System.out.println("ONE");
        }
    
        @Override
        protected void finalize() throws Throwable {
            // TODO Auto-generated method stub
            super.finalize();
            System.out.println("FINALIZED");
        }
        public static void main(String[] args) throws Throwable {
            MultipleConstruct construct = new MultipleConstruct(3);
        }
    }
    

    Q2. Also, when is garbage collector invoked? I understand gc is a daemon thread and invoked by JVM depending on heap size remaining. Does that mean, JVM waits for the program to use threshold limit of resources and then notify the gc to sweep garbage objects.

    EDIT: How does gc resolved circular references?

  • prap19
    prap19 over 12 years
    System.gc() cannot force JVM to run garbage collector. It only informs JVM that objects are open for collections.
  • DwB
    DwB over 12 years
    System.gc() does not force garbage collection. It note that garbage collection is desired, but the JVM will run garbage collection only when it wants to run it.
  • prap19
    prap19 over 12 years
    so you mean adding a finalize() method does not ensure bug free cleaning? For e.g in such cases if there is a file object open and I want to clean it before object holding that file object dies then finalize() method is of no use unless explicitly called.
  • ratchet freak
    ratchet freak over 12 years
    @prap19 yep this is why close() is relied on more than finalize()
  • prap19
    prap19 over 12 years
    close() function in case of object? is that what you mean? AS far the file is considered, that is just an example. I am concerned about destructor like behavior in JAVA
  • ratchet freak
    ratchet freak over 12 years
    @prap19 I meant close() of the Closeable interface, and many times finalize is utterly useless or there is a solution with explicit disposing of resources
  • anurag11
    anurag11 over 12 years
    point lies here that the objects must be made 'null' or destroyed to see the finalize method being called(as shown in above code).Else the finalize method will be called by JVM whenever garbage collection takes place .
  • raymi
    raymi over 12 years
    As of Java 7 there's the possibility to use automatic resource management (with try), which will automatically call close() at the end of the try-block. This will simplify disposing of objects. You shall never use finalize for disposing resources.
  • Holger
    Holger about 6 years
    There is no special treatment for circular references. That sentence is misleading. JVMs like HotSpot optimize the process for objects with trivial finalize() methods, but that's regardless of the shape of the reference graph. Further, if more than one object is pending for finalization, they may be processed in an arbitrary order or even concurrently in multiple finalizer threads.
  • Holger
    Holger about 6 years
    Even when System.gc() triggers a garbage collection, there's no guaranty to see the effect of the finalize() method (in fact, it's rather unlikely in this example), as finalization happens asynchronously after the garbage collector has enqueued the objects and here, the JVM exits right after the garbage collection.
  • shubhamgarg1
    shubhamgarg1 about 3 years
    It depens on how the JVM has been setup as well. -XX:DisableExplicitGC JVM flag can be used to configure if explicit System.gc() would have any effect or not.