特点
- 优先处理回收价值收益最大的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过程
- 初始标记,标记GC Roots直接关联的对象,添加TAMS标记(两个指针),STW
- 并发标记,从GC Roots沿着引用关系查找,如果用户线程同时修改了引用关系,添加SATB标记;此时的新对象分配到TAMS标记之外的区域;并发。
- 最终标记:处理SATB标记,STW
- 筛选回收:按照回收价值进行回收;对于一个Region:将TAMS区域之外的对象和区域内存活的对象复制到新Region后,整块Region清除,STW。
- 注:如果内存回收的速度赶不上内存分配的速度, G1收集器也要被迫冻结用户线程执行,导致Full GC而产生长时间“Stop The World”。
使用G1
- 使用G1: -XX:+UseG1GC
- 设置Region大小: -XX:G1HeapRegionSize
- GC允许等待时间:-XX:MaxGCPauseMillis
- 新生代最小值:G1NewSizePercent,默认5
- 新生代最大值:G1MaxNewSizePercent,默认60
- 内存回收的速度赶不上内存分配的速度,FullGC时线程数:ParallelGCThreads
- 开始GC,堆使用占比:InitiatingHeapOccupancyPercent