垃圾收集器(五) G1收集器

Posted by hang.li on November 20, 2022

特点

  • 优先处理回收价值收益最大的Region(Garbage First)
  • 逻辑分代,物理不分代
  • 既可以回收年轻代,又可以回收老年代
  • 保证低延迟的前提下,尽量提高吞吐量
  • 维护一个价值列表(价值:回收所获得的空间大小以及回收所需时间的加权值)
  • jdk9默认收集器

    Region

  • 将堆内存划分为多个Region,每个Region大小在1MB~32MB,并且应为2的N次幂
  • Region分为Eden,Surviver, Old, Humongous(存放大对象)
  • 一次GC,多个Region之间使用标记整理算法,GC重新排列Region位置;一个Region的回收,将其中有效数据复制到新的Region中,然后整块回收掉当前Region,使用标记复制算法
  • 当对象大小超过Region的一半,会把对象分配给几个连续的Humongous
  • Region内部维护了对象之间的关联关系(内部对象间的指向和其他指向我的Region的信息)。维护此结构耗费堆10%~20%的空间。

    GC过程

    1. 初始标记,标记GC Roots直接关联的对象,添加TAMS标记(两个指针),STW
    2. 并发标记,从GC Roots沿着引用关系查找,如果用户线程同时修改了引用关系,添加SATB标记;此时的新对象分配到TAMS标记之外的区域;并发。
    3. 最终标记:处理SATB标记,STW
    4. 筛选回收:按照回收价值进行回收;对于一个Region:将TAMS区域之外的对象和区域内存活的对象复制到新Region后,整块Region清除,STW。
    5. 注:如果内存回收的速度赶不上内存分配的速度, G1收集器也要被迫冻结用户线程执行,导致Full GC而产生长时间“Stop The World”。

img.png

使用G1

  • 使用G1: -XX:+UseG1GC
  • 设置Region大小: -XX:G1HeapRegionSize
  • GC允许等待时间:-XX:MaxGCPauseMillis
  • 新生代最小值:G1NewSizePercent,默认5
  • 新生代最大值:G1MaxNewSizePercent,默认60
  • 内存回收的速度赶不上内存分配的速度,FullGC时线程数:ParallelGCThreads
  • 开始GC,堆使用占比:InitiatingHeapOccupancyPercent