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

标签 java garbage-collection

我在很多地方都发现,java中的finalize()方法是在垃圾收集器或System.gc()成功保留了冗余对象消耗的内存而不再引用它时调用的。还发现这个方法被调用的次数不超过一次。我不是 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 在对象头(我认为)中设置了一个标志,表示它已经完成,并且不会再次完成。

javadoc明确指出:

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

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


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

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

有人这样评论:

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

由于几个原因,这不是真的。

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

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

    当类 finalize 方法永远不会返回 1 时,会出现另一种(病态)情况。当该类的一个实例被终结时,终结器线程将被卡住。当所有终结器线程都以这种方式卡住时,将无法终结更多可终结对象2

  • 如果 Object::finalize 没有在类中被覆盖,JVM 将跳过该类的终结步骤。


1 - 这可能是由于无限循环,或者是因为 finalize() 方法卡在等待锁或等待从未发生的内部或外部“事件” .另请注意,在这种情况下,“从不”可能意味着“不会很长时间”。整体影响可能是一样的。
2 - 对象将无限期地位于终结队列中。这是内存泄漏。

关于java - 如果垃圾收集器在同一代码中两次保留内存,是否可以调用两次 finalize() 方法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61847749/

相关文章:

java - java 如何确保每个 JVM 只有一个枚举实例

Java俄罗斯方 block 游戏: Having trouble visualizing how to move an object Piece of 4 distinct Tile objects

Java:使用 joda-time 将 45 天添加到 DateTime 对象会产生无意义的日期

python - 内存未释放 - PyQt4

c++ - 什么时候需要在 Ruby C 扩展中声明 volatile VALUE?

java - 如何将 fxml 加载器的位置设置为另一个包中的 fxml

java - 如何编写 Junit 测试用例来测试字符串中的重复元素计数

java - 为什么即使外部类对象被销毁,内部类实例仍保留在内存中?

java - 如何为长生命周期对象优化 Java gc

garbage-collection - 垃圾收集器如何知道堆栈帧上的引用?