【问题标题】:JVM garbage collection - tracing live objects in young generationJVM 垃圾收集 - 在年轻代中跟踪活动对象
【发布时间】:2017-03-05 04:01:47
【问题描述】:

在收集年轻代内存时,JVM 收集器仅扫描属于年轻代的那些根对象(堆中的对象可直接从根集访问),并使用写屏障支持的卡表/记忆集来确定区域可能包含包含对年轻代中对象的引用的对象。

我的问题是,如果年轻收集器确定年轻代中的特定对象仅具有来自老一代对象的单个外部引用,它如何知道老一代对象本身是否不是垃圾,因此使年轻代对象“活”并且不符合收集条件?例如,可能存在从根集直接到老年代中该对象的路径,而该路径又引用了所述年轻代对象。 年轻收集器通常认为这个年轻代对象是活的,还是它在决定忽略/收集它之前如何确定指向它的年老代对象是否是活的/垃圾?

【问题讨论】:

    标签: java performance garbage-collection jvm


    【解决方案1】:

    它怎么知道老年代对象本身是不是垃圾?

    这不是主要/完整系列的用途。假设是老一代对象不会经常死亡。

    在执行完整收集时,它会检查所有对象,但在执行次要/年轻收集时,只会清理年轻收集中的对象。

    【讨论】:

    • 感谢您的回复 - 我不太关心年老代对象的收集,而是年轻代对象在年轻 GC 期间的生存/收集。因此,如果我从您所说的内容中理解正确,如果我们有一个年轻代对象,它只有来自一个本身就是垃圾的老年代对象的传入引用,那么这个年轻代对象(它是垃圾)在年轻 GC 中幸存下来,并且只收集在在收集所述老年代对象的主要 GC 之后发生的第一次年轻 GC。
    • 基本上是的。我认为实际上“完整”代同时涉及年轻和旧空间的集合,因为“为什么不”,还因为您还需要从根和通过对象在年轻代中进行标记以找到所有可达的老一代对象。因此,您可以简单地将其设置为“在下一次完整 gc 之前不会收集这些对象”。 @Stormshadow
    【解决方案2】:

    问题是“你怎么会遇到这样的情况?”

    要创建从旧对象到年轻对象的引用,旧对象必须是可访问的,否则我们无法在其中存储对年轻对象的引用。为了在之后变得无法访问,我们必须至少修改根引用或之前引用相关旧对象的另一个旧对象。

    正如您已经提到的,JVM 会跟踪此类写入,这很关键,因为为了检测旧对象现在引用了一个年轻对象,它必须知道旧对象的内存区域(又名卡)已被修改。原则上,由于卡片标记还意味着记住传入的引用,因此 gc 现在能够检测到旧对象变得不可访问,即使没有主要 gc。它只需要考虑修改后的卡(或根集)来了解它。是否这样做,取决于环境因素,例如选择的 gc 算法,即您是使用 CMS(不会)还是 G1(可能),以及“混合集合”的配置方式或实际内存压力。

    当然,如果您使用并发收集器,则可能会在收集周期已经进行时发生使旧对象无法访问的修改。在这种情况下,在这个 gc 周期内,年轻的对象可能被认为是可达的,即使修改发生在纳秒之前。

    【讨论】:

    • 我不知道它是如何工作的。虽然使老一代对象不可访问的写入确实会被卡片标记捕获,但年轻集合不能真正使用该信息来证明任何特定的老一代对象不可访问:这样做会需要对整个 old gen 做一个满分,以了解自上次收集以来对 old gen 的 所有 写入的实际最终效果。本质上它必须做一个完整的 gc。
    • 将卡片标记视为一种保守的启发式方法:当它注意到对年轻对象的引用已写入时,它能够保守地增加可达集老一代这并不总是正确的——因为它不能确定旧的 gen 对象是否仍然可以访问,但至少它是正确的,因为一个太大的可达集是可以的。另一方面,它不能安全地减少可达集,因为该更改必须是准确的,并且仅知道更改的引用对您没有帮助。
    • @BeeOnRope:当然,这需要一个混合集合,包含更改后的卡片。由于在 OP 的假设场景中,只有一个对旧对象的唯一根引用,并且为一个区域记住了传入的引用,因此可以检测到这个单一的跨区域引用已经消失。因此,只需遍历区域即可发现没有区域内引用。我并不是说一个年轻的集合就足够了,我只是说你不需要一个完整的 gc。
    • 除了整个区域的完整集合之外,您如何合并已更改的卡片?对区域内任何对象的单次写入可能会以复杂的方式改变整个区域内每个对象的可达性。区域内引用的“记忆集”非常简单:它只是说“区域 A 中的这个对象被区域 B 中的这个对象引用”(对于 OP 的示例,A = 年轻,B = 老)。它没有为您提供任何 信息来确定更改引用如何缩小 记忆集。它只会在成长方面做得很好。
    • 当然,我们可能只是在谈论不同的事情。说起“混合收藏”,我就想到了G1。所以也许你的答案应该在那个收集器的背景下进行?在那种情况下,我们强烈同意:两个区域(具有传入引用的区域,这里是年轻区域)和具有传出引用并有脏卡的区域的“混合集合”:在传统的非-G1 收藏家这只是彼得提到的“完整收藏”。对于 G1,它可能只收集众多区域中的 2 个,因此非常不同......
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-12-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多