年轻一代集合中的活动对象是如何计算出来的?

发布于 2024-09-26 01:19:32 字数 218 浏览 8 评论 0原文

据我了解,YGC 所花费的时间与 Eden 中存活对象的数量成正比。我还了解如何在主要集合中计算出活动对象(线程堆栈中的所有对象和静态对象以及可从这些对象传递到达的其他对象。)

但我不明白如何在年轻代集合中计算出活动对象? 如果它解析线程堆栈,那么它需要解析 eden + tenured space,我认为情况并非如此。那么JVM如何找到eden中的存活对象并将它们复制到To Survivor空间中呢?

I understand that time taken by YGC is proportional to number of live objects in Eden. I also understand that how the live objects are figured out in Major collections (All the objects in thread stacks and static objects and further objects reachable from those objects transitively.)

But I dont understand how the live objects are figured out in young generation collection ?
if it parses the thread stacks, then it need to parse eden + tenured space which is not the case I think. So how does JVM find the live objects in eden and copies them in To Survivor space ?

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

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

发布评论

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

评论(3

鹊巢 2024-10-03 01:19:32

年轻代集合中的存活对象是如何计算出来的?

有关如何在 HotSpot 中实现分代收集的详细说明,请参阅本文。

一般来说,分代收集器按如下方式标记年轻代(假设我们只有两代):

  1. 它标记年轻对象并跟踪从线程堆栈帧和静态帧开始的引用。当它找到对老一代对象的引用时,它会忽略它。
  2. 然后,它对老一代中引用年轻代对象的引用重复该过程。棘手的一点是在老一代中识别这些引用,而不标记整个老一代。
  3. 现在我们已经标记了新一代中所有可访问的对象......并且其余的(在该一代中)可以被回收。

在HotSpot中,包含年轻代引用的老年代对象是使用“卡表”来标识的。老年代被划分为512字节的区域,每个区域有一个“Card”。如果该区域包含任何旧的->新一代指针,在卡中设置了一个位。然后在新一代收集期间跟踪具有卡位设置的区域中的对象。

棘手的事情是在新的空间引用写入老一代对象时维护 Card 表。在 HotSpot 中,这是使用软件写屏障来实现的,只要将新的空间引用写入与卡相对应的内存区域,该软件写屏障就会设置适当的卡的脏位。正如链接的文章所指出的,这使得在对象中设置引用字段更加昂贵,但由于大多数时候只能收集新一代而节省了时间,所以这显然是值得的。

how the live objects are figured out in young generation collection ?

A good high-level description of how generational collection is implemented in HotSpot may be found in this article.

In general a generational collector marks the young generation as follows (assuming we just have two generations):

  1. It marks young objects and traces references starting with the thread stack frames and the static frames. When it finds a reference to an old generation object it ignores it.
  2. Then it repeats the process for references in the old generation that refer to young generation objects. The tricky bit is identifying these references in the old generation without marking the entire old generation.
  3. Now we have marked all of the objects in the new generation that are reachable ... and the rest (in that generation) can be reclaimed.

In HotSpot, old generation objects that contain young generation references are identified using the "Card Table". The old generation is divided into regions of 512 bytes, and each region has a "Card". If the region contains any old -> new generation pointers, a bit in the Card is set. Objects in regions with the Card bit set are then traced during a new generation collection.

The tricky thing is maintaining the Card table as new space references are written to old generation objects. In HotSpot, this is implemented using a software write-barrier that sets the appropriate Card's dirty bit whenever a new space reference is written into the memory region corresponding to the Card. As the linked article notes, this makes setting a reference field in an object more expensive, but it is apparently worth it due to the time saved by being able to collect only the new generation most of the time.

猫性小仙女 2024-10-03 01:19:32

为了仅跟踪最年轻的一代,垃圾收集器扫描相同的根集(堆栈和寄存器),并且还扫描自上一次年轻代扫描以来已修改的所有较旧的(未收集的)代。只有那些已被修改的对象才可能指向年轻代对象,因为未修改的对象不可能指向上次修改后创建的对象。

所以棘手的部分是,GC 如何知道自上次 GC 以来哪些对象被修改了?有许多技术可以使用,但它们基本上都可以归结为跟踪对老一代对象的写入。这可以通过捕获写入(写入屏障)或仅跟踪所有写入目标(写入缓冲区、卡标记)来完成,所有这些都会在 GC 不运行时增加程序执行的开销(因此它不会显示为 GC 暂停时间,但确实显示在总运行时间中)。如果有的话,硬件支持会有很大帮助。跟踪不需要精确,只要扫描每个修改的老一代对象即可(扫描未修改的对象是浪费时间,但不会伤害任何东西)。

To trace just the youngest generation, the garbage collector scans the same root set (stacks and registers) and ALSO all the older (non-collected) generations that have been modified since the previous young generation scan. Only those objects that have been modified can possibly point at young generation objects, as unmodified objects cannot possibly point at objects that were created after their last modification.

So the tricky part is, how does the GC know which objects have been modified since the last GC? There are a number of techniques that can be used, but they basically come down to keeping track of writes to old generation objects. This can be done by trapping writes (write barriers) or just keeping track of all write targets (write buffers, card marking), all of which add overhead to the execution of the program while the GC is not running (so it doesn't show up as GC pause time, but does show up in the total elapsed time). Hardware support helps a lot, if its available. The tracking need not be exact, as long as every modified older generation object is scanned (scanning unmodified objects is a waste of time, but won't hurt anything).

梦旅人picnic 2024-10-03 01:19:32

我在这里引用 Brian Goetz 的文章中的相关文本。

跟踪垃圾收集器,例如
复制、标记-清除和标记-压缩,
全部从根集开始扫描,
遍历对象之间的引用,
直到所有活动对象都被
访问过。一代人的追踪
收集器从根集开始,
但不遍历引用
导致对象在较旧的情况下
一代,这减少了尺寸
要跟踪的对象图。

I am quoting the relevant text from the article by Brian Goetz here.

Tracing garbage collectors, such as
copying, mark-sweep, and mark-compact,
all start scanning from the root set,
traversing references between objects,
until all live objects have been
visited. A generational tracing
collector starts from the root set,
but does not traverse references that
lead to objects in the older
generation, which reduces the size of
the object graph to be traced.

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