如果垃圾回收器在同一代码中两次保留内存,是否可以两次调用finalize()方法?

我发现在很多地方,当垃圾回收器或System.gc()成功保留了冗余对象消耗的内存而没有更多引用时,将调用java中的finalize()方法。还发现该方法被调用不超过一次。我对Java并不陌生,但是经验也不多。我可能对此有误解,但让我们说一段代码

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();
    }
}

在这里,finalize方法被调用两次,因为内存堆两次有资格进行垃圾清理。因此,对于我是否正确了解整个事情还是应该按照其行为方式进行操作,我有些困惑。

评论
一南
一南

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:

“ Java虚拟机对于任何给定对象永远不会多次调用finalize方法。”

Of course, there is nothing an object method 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

有人这样评论:

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

这有两个原因,这是不正确的。

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

  2. In fact, Object::finalize is not overridden, the JVM will typically skip the finalization step.

点赞
评论