10

我有一个关于 GC 根的问题。我读到 GC 的根源之一是“实时线程”。这意味着什么?

我一直有这样的印象,每个线程都有自己的堆栈,堆栈的局部变量是线程的 GC 根,现在我很困惑。线程表示还有哪些其他类型的对象引用,它们不在帧堆栈或本机堆栈上?

另一个问题是年轻代收集是否使用 GC 根,还是仅用于主要算法?

谢谢

更新:好的,抱歉,为了简单起见:我已经阅读了这篇简短的文章:yourkit.com/docs/java/help/gc_roots.jsp,并且有一个“线程”选项作为 GC 根,这到底意味着什么线程是 GC 根吗?什么样的对象被 Thread GC root 引用,而不被它的栈引用?为什么这两个类别不同?

4

3 回答 3

5

我读到 GC 根之一是“实时线程”。这意味着什么?

活动线程是已启动但尚未终止的线程。

线程表示还有哪些其他类型的对象引用,它们不在帧堆栈或本机堆栈上?

没有任何。

当他们说(活动)线程是 GC 根时,他们的意思是(实际上)线程堆栈帧中的所有值。

(“帧堆栈”和“本机堆栈”在不同的执行模式下拥有基本相同的信息;即解释与编译。在理解 GC 根时无需区分它们。)

...这究竟意味着线程是 GC 根?

这意味着线程的堆栈是一个 GC 根,并且所有线程的堆栈帧中的所有活动变量的内容都是可访问的。

这些事情都在说同样的事情


另一个问题是年轻代收集是否使用 GC 根,还是仅用于主要算法?

(首先应该注意,并非所有 Java GC 都是分代的,我们所做的任何概括都可能被新的 GC 技术呈现为不正确的。)

年轻代集合当然可以。它需要知道所有根中的内容,以避免删除这些根引用的对象。由于 GC 根可以引用年轻代中的对象,因此年轻代收集器需要使用它们。

从某种意义上说,所有收藏家都使用它们。但在另一种意义上,GC 根仅在某些“停止世界”收集阶段直接使用。对于那些在正常线程运行时运行的收集器/阶段,用户线程可以修改 GC 根。GC 基础设施使用诸如写屏障之类的东西来捕获可能影响可达性的任何更改......以各种方式。

于 2014-10-08T10:14:00.700 回答
0

想象一个带有 java 线程对象 local new'ed 的方法,当方法退出时,对象就消失了(引用超出范围并且任何堆分配的内存都符合 GC 条件)。如果以相同的方法启动线程,那么现在该线程对象及其引用的任何内容的生存时间也与实时运行线程的生存时间相关联。在线程退出之前,仍然从正在运行的线程引用的任何内存都不符合 GC 的条件,并且该线程被称为 GC 根。

线程可以通过堆栈或堆以两种不同的方式分配内存。堆栈存储不是 GC,而是在当前堆栈帧展开时回收。当您在代码中使用“new”时,通常会分配堆存储(注意 new 并不总是意味着堆存储,请参阅转义分析)。堆是 GC'ed。

了解更多关于 GC 根的一个好方法是获取正在运行的 Java 应用程序的堆转储并将其加载到 Visual VM 或 Eclipse MAT 中,从那里您应该能够检查 GC 根。

年轻代收集将使用 GC 根,因为具有 GC 根的对象不符合 GC 的条件,但最好根据给定的算法来讨论。

于 2014-10-07T13:55:55.513 回答
0

JVM 对其线程进行分区,一些专门用于垃圾收集,一些用于其他内部 JVM 任务,还有一些执行用户提供的可执行文件部分。

在这种情况下,可达意味着用户执行线程可达。这包括必须运行的第一个线程public static void main(String[] args)和从该线程启动的所有线程,减去那些变得无法访问或完成的线程。

于 2014-10-07T14:14:34.860 回答