编程高手必学的内存知识
海纳
华为编译器高级专家,原 Huawei JDK 团队负责人
20674 人已学习
新⼈⾸单¥59
登录后,你可以任选4讲全文学习
课程目录
已完结/共 33 讲
编程高手必学的内存知识
15
15
1.0x
00:00/00:00
登录|注册

22 | G1 GC:分区回收算法说的是什么?

你好,我是海纳。
在上一节课,我们介绍了分代式垃圾回收算法。把对象分代以后,可以大大减轻垃圾回收的压力,进而就减少了停顿时长。在这种思路的启发下,人们进一步想,如果把对象分到更多的空间中,根据内存使用的情况,每一次只选择其中一部分空间进行回收不就好了吗?根据这个思路,GC 开发者设计了分区回收算法
它在实际场景中应用非常广泛,比如说 Hotspot 中的 G1 GC 就是分区回收算法的一种具体实现,Android 上的 art 虚拟机也采用了分区回收算法。而且从 JDK9 开始,G1 GC 就是 JDK 的默认垃圾回收算法了,所以在将来很长时间里,对 G1 GC 进行合理的调优,将是 Java 程序员要重点掌握的知识。
那么这节课,我们就来深入地讲解分区回收算法的基本原理,掌握 G1 GC 的若干重要参数,从而对 G1 GC 进行合理的参数调优。
要想理解分区垃圾回收的原理,还得从它的结构讲起。

分区算法的堆结构

首先,我们来了解一下分区回收算法的堆空间是如何划分的。下图是 G1 GC 的堆结构:
G1 也是一个分代的垃圾回收算法,不过,和之前介绍的 CMS、Scavenge 算法不同的是:G1 的老年代和年轻代不再是一块连续的空间,整个堆被划分成若干个大小相同的 Region,也就是区。Region 的类型有 Eden、Survivor、Old、Humongous 四种,而且每个 Region 都可以单独进行管理。
确认放弃笔记?
放弃后所记笔记将不保留。
新功能上线,你的历史笔记已初始化为私密笔记,是否一键批量公开?
批量公开的笔记不会为你同步至部落
公开
同步至部落
取消
完成
0/2000
荧光笔
直线
曲线
笔记
复制
AI
  • 深入了解
  • 翻译
    • 英语
    • 中文简体
    • 中文繁体
    • 法语
    • 德语
    • 日语
    • 韩语
    • 俄语
    • 西班牙语
    • 阿拉伯语
  • 解释
  • 总结

G1 GC是Java程序中广泛应用的一种分区回收算法的具体实现。文章介绍了G1 GC的堆结构、写屏障、垃圾回收模式以及相关参数调优。G1 GC将堆空间划分为多个大小相同的Region,包括Eden、Survivor、Old和Humongous四种类型,每个Region可以单独管理。其特点是维护跨分区引用,其中的关键是写屏障,采用开始时快照(SATB)技术来解决活跃对象漏标问题。G1的垃圾回收模式有两种:young GC和mixed GC,其中mixed GC会回收全部的年轻代Region,并回收部分老年代Region。决定老年代Region是否被回收的因素包括垃圾占比和建议的暂停时间。文章还介绍了几个常用的G1参数,方便读者在实践中对G1进行调参。整体而言,本文深入浅出地介绍了G1 GC的原理和应用,对于Java程序员来说是一份重要的知识参考。 G1 GC的特点包括维护跨分区引用、垃圾回收模式的young GC和mixed GC、以及相关参数调优。

仅可试看部分内容,如需阅读全部内容,请付费购买文章所属专栏
《编程高手必学的内存知识》
新⼈⾸单¥59
立即购买
登录 后留言

全部留言(9)

  • 最新
  • 精选
  • 满分💯
    「因为 Evacation 发生的时机是不确定的,在并发标记阶段也可能发生」如果并发标记没有结束,nextBitMap 可以赋值给 prevBitMap吗?那是怎么保证 Evacation 开始的时候 prevBitMap 可用的呢?

    作者回复: 实际上bitmap不存在也是可以的。使用DFS也足够保证Evacuation的过程是正确的。那么bitmap的作用除了计算垃圾的比例,还有就是可以加速跨region的引用的对象活跃性判断。从这个角度看,prevBitMap只要有就能加速转移的过程,哪怕它只是描述一部分空间内的对象是否活跃。当Evacuation开始时,prevBitMap有多少就用多少好了。prevTAMS到top之间的对象都交给DFS去处理就行了。

    2021-12-29
    2
  • 李二木
    Garbage First原来是指老年代 Region 的垃圾占比高,就有可能优先被回收。因为年轻代是全部回收。

    作者回复: 对的。

    2021-12-17
    1
  • csyangchsh
    老师,对下面这句话,我有一个疑问,Mixed GC CSet的确定是应该在并发标记后根据region的垃圾对象的比例选择的,那么在这之前如何知道哪些region在CSet中?对于YGC来说,所有Old -> Young的引用都要记录吧。这个地方是不是应该改成“老年代 Region 到年轻代 Region 的引用, 和老年代 Region 到 老年代 Region 的引用。”? “RSet 需要维护的引用关系只有两种,非 CSet 老年代 Region 到年轻代 Region 的引用,和非 CSet 老年代 Region 到 CSet 老年代 Region 的引用。”

    作者回复: 你的想法是对的。一开始CSet是空的,所以所有的老年代Region都不属于CSet。随着标记的进行,一些老年代Region的垃圾比例超过一定阈值就会被添加到CSet中,那么从它出发的引用就不用再管了。所以CSet的构建并不是一下子完成的。这样有助于提高效率。

    2021-12-31
  • Alexyz
    老师,采用SATB设计解决了漏标的问题,但会不会将本来可能是需要被回收的对象错标了呢?如果会,G1怎么解决的这种情况呢?

    作者回复: 这不就是多标么。多标会产生浮动垃圾,但下一次会被回收掉。原文中有的,可以再仔细读读

    2021-12-28
  • 费城的二鹏
    老师没有讲,哪些部分是stw的,感觉 Evacation 应该是 stw 的。 思考题:从最大停顿时间角度考虑,需要尽量全部操作并发,root扫描目前很难并发,所以接下来应该是解决并发copy的难点,实现减少最大停顿时间。

    作者回复: 是的。目前讲到的内容来说,evac阶段都是stw的,下节课才讲如何在copy阶段也可以并发。

    2021-12-19
  • Geek_825682
    引用消失--》write barrier标记灰色--》业务线程执行,增加耗时--》空间换时间--》SATB队列。
    2023-06-01归属地:北京
  • Spoon
    RSet里面存放的数据 1.稀疏表是一个哈希表,存放的是Card,哈希表的Key是引用关系吗? 2.细粒度表则是一个真正的 card table,引用当前Region的Region的Card table? 3.粗粒度表则是一个区的位图,是不是将所有Region做成bitmap?
    2023-01-21归属地:浙江
  • 李二木
    G1回收算法只是选择复制算法吗?
    2022-05-23
  • 满分💯
    1. prevBitMap 中记录的应该是活跃对象起始地址吧,但是怎确定对象的大小呢?难道是按照固定块大小搬移对象的吗? 2. G1 中对象的分配应该是基于空闲链表分配对象的吧,垃圾回收的时候是不是把回收的region归还到空闲链表中。
    2022-02-24
收起评论
显示
设置
留言
9
收藏
沉浸
阅读
分享
手机端
快捷键
回顶部