[英]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.