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

发布于 2024-12-12 01:32:51 字数 572 浏览 0 评论 0原文

我正在使用 jvisualvm 来检查应用程序中的内存泄漏。当我进行堆转储时,有时会出现几个本应被垃圾收集的对象处于打开状态。

当我对它们执行“显示最近的 GC Root”命令时,它显示根是我定义的一个类,它实现了 Runnable 接口。该参考被列为(java框架),我知道这与线程有关。当我展开此节点的树时,它会打开并显示 。因此,很明显,这不是我公开的参考资料,而是 Java 内部的东西。

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

那么,Java 是否会在某个地方保留对最后一个 Runnable 的引用,以使其保持打开状态?有什么方法可以告诉 Java 释放此引用,以便可以为我的堆转储正确收集它的垃圾吗?

这是怎么回事?

I'm using jvisualvm to check for memory leaks in my application. When I do a heap dump, sometimes several objects are being held open that should have been garbage collected.

When I do a "Show Nearest GC Root" command on them, it shows me that the root is a class which I defined which implements the interface Runnable. The reference is listed as (java frame), which I know has something to do with threading. When I expand the tree for this node, it opens up and shows <no references>. So it seems pretty clear that this is not a reference I'm keeping open, but something internal to Java.

The GC Root object listed in jvisualvm is of type AnalyticNode extends Node which in turn is Node implements Runnable. This root object in no way has anything to do with AWT, Swing, or any heavyweight user interface components, despite the word "frame" being used. In this case, the word "frame" refers to threading.

So does Java keep a reference to the last Runnable somewhere that would be holding this open? Is there any way that I can tell Java to release this reference so it can be properly garbage collected for my heap dump?

What's going on here?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

只想待在家 2024-12-19 01:32:51

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


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

我可以重现与工作线程中的代码所描述的情况相匹配的情况:

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

清理 target 的声明,使其位于循环内可以修复问题。

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

In this context, "frame" refers to a stack frame. It sounds like this Runnable, instead of (or in addition to) being the target of a running thread, is stored in a local variable in a frame on the stack of an executing thread. It will be eligible for collection when the method associated with the frame returns.


Based on subsequent comments, my guess is that in your custom thread pool, there's a local variable to which the Runnable is assigned. It's probably in too large a scope (outside a loop) and is not being cleared (assigned null) after each iteration of the loop.

I can reproduce a situation that matches what is described with code like this in a worker thread:

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

Cleaning up the declaration of target so that it is inside the loop fixes the problem.

I'd suggest switching to an Executor implementation from core Java, or posting the relevant code of your custom thread pool if you want to fix it.

聚集的泪 2024-12-19 01:32:51

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

What did you do with the object you created? Did you create a thread and point it to it? In that case you must make sure the thread has been stopped by allowing the code in run() to finish running.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文