GC.run 和 GC.run_finalization 有什么区别?

What is the difference between GC.run and GC.run_finalization?

谁能给我解释一下(最好能提供文档)这两者有什么区别:

jcmd ${jpid} GC.run_finalization
jcmd ${jpid} GC.run

正如在应用程序 (springboot + tomcat) 中一样,经过测试(使用加特林)后,大量内存保持分配状态,没有被释放。 在应用程序生命周期中:

我找到的唯一文档是 https://docs.oracle.com/javase/8/docs/api/java/lang/System.html#gc-- ,但它让我更加困惑(我知道 GC.run_finalization 会建议最终确定 objects 发布,而 GC.run 会建议内存 objects 为将来重用做好准备,不必释放)。

提前致谢

(best would be to lead to documentation)

这里有 jcmd 及其子命令的文档:

该文档说明 jcmd <pid or class> help 将列出可用的命令,jcmd <pid or class> help <command> 将为您提供 <command> 的帮助信息。


What is the difference between GC.run and GC.run_finalization?

通过简要查看 JVM 源代码,我可以得出以下结论:

  • GC.run 运行是一次完整的垃圾回收。我不知道终结器是否 运行(立即),但我怀疑不是。

  • GC.run_finalization 只是调用 System.runFinalization()。根据 javadoc,这个 运行s 终结器在等待终结的对象上;即 GC 已经 找到的 Java 个对象:

    1. 当前无法访问,
    2. 有一个非默认的 finalize() 方法,并且
    3. 尚未标记为最终确定。

(I understood that GC.run_finalization would suggest finalization of objects for release while GC.run would suggest memory objects to be prepared for future reuse and not necessary freed).

不是这样的。一个正常的 GC 循环是这样的:

  • 垃圾回收找到所有无法访问的对象。
  • 任何需要完成的无法访问的对象都会添加到队列中。
  • 立即删除其他无法访问的对象。
  • GC 结束
  • 终止线程唤醒并开始处理其队列中的对象。
    • 调用每个排队对象的 finalize 方法并将其标记为已完成。

完成的对象留在原处。它们将在以后的收集中被 GC 删除 前提是它们仍然无法访问

请注意,终结是一种旧机制,用于在对象被删除之前整理对象。绝大多数 Java 对象从未最终确定。


这就是对您所看到的行为的解释。

  • 浅锯齿是小集。他们只是在收集伊甸园space。据推测 "attack" 导致许多对象被保留到旧的 space.
  • 调用 GC_run 会触发收集所有 space 的完整收集。这会导致释放更多内存。
  • 调用 GC_run_finalization 无效,因为终结不会释放对象。而且队列中可能没有可终结的对象。
  • -