【问题标题】:When is finalize() invoked during garbage collection?垃圾回收期间何时调用 finalize()?
【发布时间】:2019-05-23 03:07:11
【问题描述】:

发件人:

https://www.baeldung.com/java-memory-management-interview-questionsQ11

当一个对象符合 GC 条件时,垃圾收集器必须对其运行 finalize();此方法保证只运行一次,因此收集器将对象标记为已完成并让它休息直到下一个循环。

我有几个问题要问:

  • 这个说法正确吗?
  • 是否在标记阶段,垃圾收集器是否调用 finalize() 方法?
  • 为什么它要休息到下一个周期?

P.S:我明白 finalize() 最终在 Java 9 中被弃用了。感谢决定这样做的好灵魂。

【问题讨论】:

  • 是的,没错。我忘记了 Java 规范对 finalize 的具体规定,所以我不知道它是否准确说明了 GC 将调用 finalize() 的哪个阶段,但 “有资格进行垃圾收集” 是重要的一点。那是一个对象可以finalize()
  • @markspace 规范 (JLS 12.6) 没有说明任何阶段。这是一个实现细节。

标签: java memory-management garbage-collection finalize


【解决方案1】:

是在标记阶段,垃圾回收器会调用finalize()方法吗?

依赖于实现,但通常不会。 GC 完成后由后台线程调用终结器。

请记住,GC 可能是一个停止世界的事件,并且应该尽可能短。终结器方法可能很慢,因此不应在 GC 期间调用它们。

为什么要休息到下一个周期?

在高级(简化)上,它的操作如下(有关术语,请参阅JLS 12.6.1):

  • GC 检测到不可达的对象:

    • 如果对象具有终结器方法,请将其添加到终结器队列中。
      该对象是可终结的

    • 如果对象可以从 finalizable 对象访问,则离开它。
      该对象是finalizer-reachable

    • 否则现在回收内存。
      该对象无法访问

  • 后台终结器线程处理排队的finalizable对象:

    • 调用finalize() 方法。
      当方法返回时,对象是finalized
  • 由于 GC 已经完成,finalized 对象正在“休息”直到下一个 GC 周期。

  • 在下一个 GC 循环中,带有标记为 finalized 的终结器方法的对象被视为 unreachable,并且内存将被回收(假设终结器方法没有t 再次使对象可达)。

请注意,当一个对象可终结时,可能会发生许多 GC 周期,即终结器线程可能需要一段时间来处理该对象。

【讨论】:

  • 在实践中,实现不会将对象标记为“已完成”,而是在创建时将具有非平凡finalize() 的对象标记为“未完成”,在变为可终结时不标记。所以垃圾收集器不需要区分没有终结器的不可达对象和已经运行终结器的不可达对象。重要的是要记住,当 finalize() 方法返回时,对象可能不是不可访问的(应该是,但该方法可能包含任意代码)。
猜你喜欢
  • 1970-01-01
  • 2015-10-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-12-21
相关资源
最近更新 更多