阅读文档,记录一些重要的点。
G1的使用场景,在多核处理器的情况下
- 几十G或者更大的内存,堆超过50%被活动数据占据。
- 对象分配和晋升的速率可能会随时间发生显著变化。 应该就是指对象被长期使用,不是朝生夕死的那种。
- 堆中存在大量碎片。
- 可预测的暂停目标,不需要几百毫秒。
JDK9以上是默认的,可以用-XX:+UseG1GC手动指定使用
特点
- 分代
- 并行
- 大多数并发
- 会stop-the-world
根据应用历史行为,垃圾回收信息,优先回收性价比最高的区域,就是垃圾最多的。
G1主要通过回收机制来释放空间:将选定内存区域中发现的可收集活对象复制到新内存区域,并在过程中进行压缩。完成回收后,应用程序可重新利用原先被活对象占用的空间进行分配。
G1不是实时的垃圾回收期,会尝试实现暂停的目标,但是不保证一定完成。
灰色的是没有使用的,请求来的时候,管理器会把小region标记为yong代或者old代,然后返回给应用程序使用。 红色的就是yong代,红色带s的是yong代中的servivor区域. 蓝色的old代,蓝色带h的是放大对象的humongous区域。
除了巨大对象,都是分配到年轻代的eden区
G1回收的两个阶段
- young-only
a. Concurrent Start 启动年轻代的收集,同时标记老年代还活着的对象
b. Remark stop-the-world 说明标记结束了,这个时候会释放引用,卸载类,
c. Cleanup stop-the-world 决定是否进入空间回收阶段,如果进入空间回收阶段,如果回收的话,就会变成single Prepare Mixed young collection操作 - Space-reclamation phase
除了清理yong region以外,还会复制转移old region中存活的对象,也叫Mixed collections,直到G1认为回收性价比不高的时候停止 如果统计信息的时候,发生了out of memeroy 则执行一次full gc
垃圾收集和空间释放,都是在stop-the-world的时候执行的。此外
- 年轻代的对象,根据代数决定移动到servivor或者old
- old只能移动到old
- 超大对象humogous region如果对象不用了,可以回收,否则除非万不得已,是不移动的。
每一个region都被划分成512byte的card,这些card是标记的最小单位
Remenber Set
- 记录哪些region的card引用了本region中的对象,并不会存储引用所在的位置,而只是记录大概的位置,在哪些card里。
- 懒创建的,在Remark和Clean Up暂停的中间,G1重建所有被选中的Region中的Collect Set对应的Remenber Set 3.每个region都有一个RemenberSet存储了所有引用这个region的位置,CollectSet就是根据这个生成的。
Collect Set
-
Collect Set 是一个要回收的region集合。依赖垃圾回收阶段的类型 在yong only阶段,collect set 仅由 年轻代的region,可能回收的的大对象的humongous region 组成 在Space-Reclamation阶段,collect set 由 年轻代的region,可能回收的的大对象的humongous region,和一些候选的老年代region组成。
-
在 G1 的空间回收阶段,系统会挑选一批“候选区域”作为潜在的回收目标。
选择时考虑:
- 区域内活对象少(可回收多);
- 区域之间引用关系少(调整代价低)。
对那些能回收空间太少(低于 G1HeapWastePercent 阈值)的区域,G1 会直接放弃,不在本次回收中处理。
在Remark和CleanUp两次暂停中间,G1开始为接下来的收集准备。 随着Clean UP的暂停结束这个工作,并且结束根据region的回收价值排序,在随后的Mix collections阶段会更偏好收集这样的区域。
回收步骤
- Pre Evacuate Collection Set 断开应用线程的TLAB,选出要收集的区域,从CSet中,以及其他的准备工作
- Merge Heap Roots 合并Root,创建一个统一的Rset,把要收集的region中的Rset进行合并,如果不合并后面并行的时候要花费更大的代价来过滤
- Evacuate Collection Set 递归内部引用,不断把活着的对象拷贝出去,
- Post Evacuate Collection Set 处理引用,恢复用户线程。