首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在年轻一代的收藏中,活的物体是如何被计算出来的?

在年轻一代的收藏中,活的物体是如何被计算出来的?
EN

Stack Overflow用户
提问于 2010-10-03 14:26:39
回答 3查看 1.8K关注 0票数 8

我知道YGC所花的时间与伊甸园中的活物体数量成正比。我还了解如何在主要集合(线程堆栈中的所有对象和静态对象,以及可从这些对象传递的更多对象)中计算出活动对象。

但我不明白在年轻一代的收藏中是如何弄清楚这些活的物体的?如果它解析线程堆栈,那么它需要解析eden +租期空间,但我认为情况并非如此。那么JVM如何找到伊甸园中的活动对象并将它们复制到To Survivor空间呢?

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2010-10-03 16:09:41

如何在年轻一代的收藏中计算出活的对象?

this article中可以找到关于如何在HotSpot中实现分代集合的高级描述。

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

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

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

棘手的事情是维护Card表,因为新的空间引用被写入到老一代的对象中。在HotSpot中,这是使用软件写屏障实现的,每当将新的空间引用写入与卡对应的存储区时,该写屏障就会设置适当的卡的脏位。正如链接的文章所指出的那样,这使得在对象中设置引用字段的成本更高,但显然是值得的,因为大多数时候只能收集新一代的数据,从而节省了时间。

票数 9
EN

Stack Overflow用户

发布于 2010-10-03 16:05:12

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

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

票数 3
EN

Stack Overflow用户

发布于 2010-10-03 15:46:56

我在这里引用了article by Brian Goetz中的相关文本。

跟踪垃圾收集器,如复制、标记-清除和标记-压缩,都从根集开始扫描,遍历对象之间的引用,直到所有活动对象都被访问。分代跟踪收集器从根集开始,但不会遍历指向前一代中的对象的引用,这会减小要跟踪的对象图的大小。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/3848830

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档