繁体   English   中英

当我在jvisualvm中转储堆时,如何删除对Runnable的“Java Frame”GC根引用?

[英]How can I remove a “Java Frame” GC Root reference to a Runnable when I dump a heap in jvisualvm?

我正在使用jvisualvm来检查我的应用程序中的内存泄漏。 当我进行堆转储时,有时会有几个对象被打开,应该是垃圾回收。

当我对它们执行“显示最近的GC根”命令时,它向我显示根是我定义的类,它实现了Runnable接口。 引用列为(java frame) ,我知道它与线程有关。 当我展开该节点的树时,它会打开并显示<no references> 所以很明显,这不是我保持开放的参考,而是Java内部的东西。

jvisualvm中列出的GC Root对象的类型为AnalyticNode extends Node ,而Node implements Runnable 尽管使用了“frame”一词,但这个根对象绝不与AWT,Swing或任何重量级用户界面组件有任何关系。 在这种情况下,单词“frame”指的是线程。

那么Java是否会保留对最后一个Runnable的引用? 有什么方法可以告诉Java发布这个引用,以便它可以正确地为我的堆转储垃圾收集?

这里发生了什么?

在此上下文中,“帧”指的是堆栈帧。 听起来像Runnable ,而不是(或除了)作为正在运行的线程的目标,存储在执行线程的堆栈中的帧中的局部变量中。 当与框架关联的方法返回时,它将有资格进行收集。


根据后续评论,我的猜测是在您的自定义线程池中,有一个分配了Runnable的局部变量。 它可能在一个范围太大(在循环之外)并且在循环的每次迭代之后没有被清除(指定为null )。

我可以在工作线程中重现与此类代码相似的情况:

Runnable target = null;
while (true) {
  target = queue.take();
  target.run();
}

清理target声明以使其在循环内部可以解决问题。

我建议从核心Java切换到Executor实现,或者如果要修复它,则发布自定义线程池的相关代码。

你用你创造的对象做了什么? 你创建了一个线程并指向它吗? 在这种情况下,您必须通过允许run()中的代码完成运行来确保线程已停止。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM