简体   繁体   中英

Can the finalize() method be called twice if the garbage collector retains memory twice in the same code?

I found it in many places that the finalize() method in java is called when the garbage collector or System.gc() has successfully retained the memory consumed by the redundant object with no more references to it. Also found that this method is called not more than a single time. I am not new to java but also not pretty much experienced. I may have a wrong understanding of it but let's say a piece of code

public class Solution {
    @Override
    protected void finalize(){
        System.out.print("method called");
    }
    public static void main(String... args){
        Solution obj1= new Solution();
        Solution obj2 = new Solution();
        Solution obj3 = new Solution();
        System.gc();
        obj1=obj2;
        System.gc();
        obj3=null;
        System.gc();
    }
}

Here, the finalize method is called twice because the memory heap becomes eligible for garbage cleaning two times. So, I am a bit confused whether I know the whole thing right or if it is supposed to behave the way it's behaving.

No. The finalize() method will only be called once by the GC on an object. The JVM sets a flag in the object header (I think) to say that it has been finalized, and won't finalize it again.

The javadoc states this explicitly:

" The finalize method is never invoked more than once by a Java virtual machine for any given object. "

Of course, there is nothing to stop an object method from calling this.finalize() any number of times.


Note that finalize() is deprecated in Java 9 and later for reasons stated in the javadoc. It is recommended that you switch to using one of the following instead:

  • AutoCloseable + try with resources
  • Cleaner
  • PhantomReference

Someone commented thus:

finalize() is called for every Object that is collected.

This is not true for a couple of reasons.

  • The javadoc explicitly states that there are no guarantees that finalize will ever be called. The thing that is guaranteed is that it will be called (once) before an object's storage is reclaimed. That is a weaker statement than the statement that the comment makes.

    One scenario where garbage collected objects may not be finalized is if the JVM exits soon after a GC run.

    Another (pathological) scenario occurs when a classes finalize method never returns 1 . When an instance of that class is finalized, the finalizer thread will get stuck. When all finalizer threads are stuck in that way, no more finalizable objects can be finalized 2 .

  • If the Object::finalize is not overridden in a class, the JVM will skip the finalization step for that class.


1 - This could be due to an infinite loop, or because the finalize() method gets stuck waiting on a lock or waiting for an internal or external "event" that never happens. Note also that "never" could mean "not for a long time" in this context. The overall impact can be the same.
2 - The objects will sit in the finalization queue indefinitely. This is a memory leak.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM