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) 中一样,经过测试(使用加特林)后,大量内存保持分配状态,没有被释放。
在应用程序生命周期中:
- 攻击开始(加特林模拟),额外的 tomcat 执行线程
开始,攻击结束
- 一段时间后 spring/tomcat 会话 objects 超时 (session.servlet.timeout)
- 我希望会话 objects 被释放,额外的 tomcat 执行器被释放,但它没有发生
- 我等了很长时间(比方说几天)...这是上图的起点
- 如果我执行 GC.run_finalization - 没有任何反应(只是更快 "saw drop")
- 如果我执行 GC.run - 内存被释放,如图所示
我找到的唯一文档是 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 个对象:
- 当前无法访问,
- 有一个非默认的
finalize()
方法,并且
- 尚未标记为最终确定。
(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
无效,因为终结不会释放对象。而且队列中可能没有可终结的对象。
-
谁能给我解释一下(最好能提供文档)这两者有什么区别:
jcmd ${jpid} GC.run_finalization
jcmd ${jpid} GC.run
正如在应用程序 (springboot + tomcat) 中一样,经过测试(使用加特林)后,大量内存保持分配状态,没有被释放。
- 攻击开始(加特林模拟),额外的 tomcat 执行线程 开始,攻击结束
- 一段时间后 spring/tomcat 会话 objects 超时 (session.servlet.timeout)
- 我希望会话 objects 被释放,额外的 tomcat 执行器被释放,但它没有发生
- 我等了很长时间(比方说几天)...这是上图的起点
- 如果我执行 GC.run_finalization - 没有任何反应(只是更快 "saw drop")
- 如果我执行 GC.run - 内存被释放,如图所示
我找到的唯一文档是 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 个对象:- 当前无法访问,
- 有一个非默认的
finalize()
方法,并且 - 尚未标记为最终确定。
(I understood that
GC.run_finalization
would suggest finalization of objects for release whileGC.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
无效,因为终结不会释放对象。而且队列中可能没有可终结的对象。
-