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

Java 如果垃圾收集器在同一代码中保留内存两次,finalize()方法能否调用两次?,java,garbage-collection,Java,Garbage Collection,我在很多地方发现,当垃圾收集器或System.gc()成功地保留了冗余对象所消耗的内存而不再引用它时,java中的finalize()方法被调用。还发现此方法调用不超过一次。我对java并不陌生,但也不是很有经验。我可能有一个错误的理解,但让我们说一段代码 public class Solution { @Override protected void finalize(){ System.out.print("method called"); }

我在很多地方发现,当垃圾收集器或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方法被调用两次,因为内存堆有资格进行两次垃圾清理。因此,我有点困惑,我是否知道整个事情是正确的,或者它是否应该按照它的行为方式进行。

否。
finalize()
方法只会被GC在对象上调用一次。JVM在对象头中设置了一个标志(我认为),表示它已经完成,不会再完成

缔约国明确表示:

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

当然,没有什么可以阻止对象方法多次调用this.finalize()


请注意,
finalize()
在Java 9及更高版本中由于javadoc中说明的原因而被弃用。建议您改为使用以下选项之一:

  • AutoCloseable
    +尝试使用资源
  • 清洁剂
  • PhantomReference

有人这样说:

为收集的每个
对象
调用
finalize()

这是不正确的,原因如下

  • javadoc明确声明不保证将调用
    finalize
    。可以保证的是,在对象的存储被回收之前,它将被调用(一次)。这是一个比评论中的陈述更弱的陈述

    垃圾收集对象可能无法最终确定的一种情况是JVM在GC运行后很快退出

    当类
    finalize
    方法包含无限循环时,会出现另一种(病理性)情况。当该类的实例被终结时,终结器线程将被卡住。当所有终结器线程都以这种方式卡住时,将不再终结更多的可终结对象。他们将永远坐在终结队列中,泄漏内存

  • 如果类中未重写
    对象::finalize
    ,JVM将跳过该类的终结步骤


  • 它被调用了两次,因为两个不同的实例正在被GCdOr调用。我是否误解了这个问题?
    finalize()
    是为每个收集的对象调用的。好吧,所以它不会被调用一次,而不管收集的对象的数量如何?每当从内存堆中作为垃圾收集一个不同的对象时,它就会被一次又一次地调用?另一种情况是:创建一些对象,这些对象的
    finalize()
    方法包含一个无限循环,并让它们被收集。一旦所有终结器线程都处于忙碌状态,就不会调用其他收集对象的finalize()方法。