G1 垃圾回收器
G1:garbage frist 优先回收垃圾存放最多的分区,垃圾回收暂停时间短,同时也能维持较好的吞吐量
特点&原理
-
采用分而治之的思想,原本的堆空间分为新生代,老年代两块完整的空间,好比将房间分为了 N 个小分区
-
分区存放对象,能存放的对象类型
-
old 类型对象
-
young 类型对象
-
survivor 生还对象
-
eden 新生对象
-
Humongous大对象,跨区存放
- 特点
-
并发收集
-
压缩空间不会延长 GC 的暂停时间(能控制时间)
-
更易于预测的 GC 暂停时间 新老年代的占比 在分代模型里默认为 1:2 在 G1 模型中无需指定,G1 预测时间停顿的基准,跟踪每一次的 ygc 的耗时,若本次耗时久,那么房东就只给你分配小一点的空间,保证垃圾回收器降低停顿时间。
-
分区放的对象不固定。A region 本是 young 经历一次回收之后可能用来存放 old/survivor...
-
-
适用场景: 不需要吞吐量特别高的的场景,但是需要特别快的响应时间
基本概念
-
Card Table: 在 G1 中内存区域已经划分成了一小块的 Region,如果一个对象被其他对象持有引用时候在 card table 上记录下来;好比包租婆有手里有一堆房子租给了租客,并用一张纸记录了那个房子租给了哪个租客,有些退房了,没有被其他租客持有引用了,这个房间就会被标识出来,而这张纸就是 card table。
-
Collection Set: 当一批租客退房了,那么包租婆就得清理一下房子(region),但是同时空出来的房子又比较多,包租婆就单独搞了一张纸,记录下那些房子是需要请清洁工清洁的。这张要给到清洁工(垃圾回收器)的纸就是 collection set。
-
Remember Set: 租客 102 手里也有一张纸,记录我在隔壁 101,103 借了我哪些东西,那么清洁工不需要在整顿的时候,不用挨个挨个房间的去找 102 房间的空调遥控器被谁借走了(持有引用)。这张纸就是 Remember Set。从而保证 G1 这个清洁工能高效的回收,但是也有空间上的浪费,每个房间都得有一个账本去记录谁谁谁从我这里借走了什么。
- MixedGC: 相当于 CMS,当分区的垃圾阈值达到指定的阈值(默认 45%)
-
初始标记 STW:找到根对象
-
并发标记:顺着根往下找
-
最终标记 STW:
-
筛选收集 STW:将分区中的存活对象先拷贝并压缩到一个空的分区
-
-
参数: XX:initiatingHeapOccupacyPercent
什么时候用 G1 什么时候用 PS
G1:垃圾回收暂停时间短,吞吐量较 PS 降低了 10-15% PS:200 毫秒的的 STP
G1 回收器出现 FGC 怎么处理?
-
扩内存
-
提高 CPU 性能
-
降低 MixedGC 阈值(默认是 45%):当你分区的垃圾堆放到更小的占比的时候就通知清洁工处理,勤打扫,避免下次一打扫就是 3 天,丢失三天房租的成本。避免发生 Full GC
三色标记
-
黑色:自身和成员变量都标记完成
-
灰色:自身已标记,成员变量未标记完成
-
白色:自身和成员变量都没有标记
- 漏标:
-
出现的原因:并发标记阶段有以下模型:A持有B的引用,B持有D的引用
A(黑色) -> B(灰色) -> C(白色)
-
此时当 B 剪掉了 C 的引用,与此同时而 A 又拿到了 C 的引用,而 C 此时还是一个白色,下次垃圾回收器来了可能就会把 C 清理了,而实际 C 的引用还被 A 拿着; --所以要解决以上问题,就是要解决 C 的漏标问题;
-
incremental update 增量更新,-关注引用的增加:A 拿到 C 的引用的时候,将 A 变为灰色,下次保证能重新被扫描到。
-
SATB(snapshot at begining)-关注引用的删除 ,B 剪掉了 C 的引用时候,将这个引用关系记录到前台小妹妹的账本上(GC 堆栈)上,让清洁工打扫的时候先前台妹妹那问一下这两个房间是不是真的退还了各自的空调遥控器(是否确实不持有引用),而每个房间又存了一张账单 Remember Set,也不用扫描整个堆,从而轻松的能定位到引用关系。
下期内容规划:
-
颜色指针
我是山海哥,目前是就职于一家生鲜电商公司的一个四年Java工具人。爱分享、爱生活。
山海哥的更多私房笔记在我的公众号【Java壹码平川】,山海哥想和你交个朋友。