我刚刚读了一些关于G1算法的博客。
记忆集的用法对我来说很困惑。
我的想法是这样的:
既然我们可以使用 DFS 遍历 GC-Roots 中的每个引用,为什么我们需要记住集呢?
因为所有的博客都说我们使用remembered-set的原因是我们不需要检查每个区域是否有GC-Roots引用的对象
你需要明白什么Card Table
是第一,国际海事组织。你如何扫描only young generation
区域并清理它,如果有来自的引用old generation
回到young
?您需要准确“跟踪”这些连接存在的位置 - 因此在扫描时young generation
你可以在不破坏堆的情况下清理它。
想想看:你不能将对象标记为删除A
现在是年轻一代,如果有参考的话B
到它,从old generation
。但请记住,现在 - 你是年轻的集合中的一员only。所以要追踪这些“联系”Card Table
已实施。该卡表中的每一位都表示老年代的某个部分是“脏的”,这意味着也扫描老一代的那部分在扫描年轻时。
你为什么需要那个?扫描 young 的全部目的是扫描堆的一小部分,而不是全部。这card table
实现了这一点。
G1
有区域。如果您正在扫描怎么办regionA
你会看到它有指向其他一些的指针regionB
?只需将此信息放入Card Table
是不足够的。你的牌桌只会知道regionA
,下次扫描时regionB
- 你怎么知道你应该扫描regionA
还?如果你不这样做,显然堆完整性就被破坏了。
像这样 :remembered sets
。这些集合由异步线程填充:它扫描card table
根据该信息,它还会扫描这些“脏”区域的指针指向的位置。它会跟踪这一点regionA -> regionB
联系。每个地区都有自己的remembered set
.
所以当你到达需要发生GC的点时,当扫描时regionB
你也看看它的remembered set
并发现您还需要扫描regionA
.
在实践中,这就是为什么G1
成为一代人:这些remembered sets
原来是huge。如果将堆划分为young
and old
,没有必要保留年轻代之间的连接,无论如何你都一次扫描它们,从而消除了这些集合大小上的烧毁。G1
想要保留那个200ms
(默认)承诺 - 为此,您需要扫描年轻一代一次全部(因为区域之间没有联系remembered sets
否则堆完整性就会消失),但同时如果你使年轻代变小 - 的大小remembered sets
会很大。
因此,恕我直言,触摸这些设置是一个工程奇迹。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)