简介
G1 is a generational, incremental, parallel, mostly concurrent, stop-the-world, and evacuating garbage collector which monitors pause-time goals in each of the stop-the-world pauses.
在内存空间划分上,G1将堆分为等大的一块区域(region),region是内存分配和垃圾回收的基本单位,其大小为2的幂,范围是 1 MB 到 32 MB 之间,可通过-XX:G1HeapRegionSize=4M
进行配置。
G1在逻辑上将堆分为年轻代和老年代两种逻辑类型,年轻代又包含 eden region
和 survivor region
,所有新建的对象均创建在eden region
中,在经过young gc后,对象被复制整理到survivor region
中(年龄不够到老年代时); 老年代包含可横跨多个region的 humongous
区域,大对象指的是超过Region Size 一半大小的对象,这样的对象多了会造成 Heap 空间碎片化。示意图如下:
对象何时进入老年代:
- 存活对象超过年龄阈值(默认 15)仍未被回收则进入老年代:熬过一次 GC 增加一岁,默认年龄超过 15 岁还没有被回收则被移动到老年代,通过设置 jvm 参数
-XX:MaxTenuringThreshold
来设置对象进入老年代的阈值; - 大对象直接进入老年代:超过 G1HeapRegionSize 的一半会被认为是大对象,大对象直接进入老年代;
- 动态年龄判断:在survivor区中,所有年龄的对象的所占空间的累加和大于survivor空间的百分之
-XX:TargetSurvivorRatio
值(默认50),大于或等于最大年龄的对象,都可以进入老年代;可参考:JVM-对象什么时候进入老年代(实战篇) - 空间分配担保:young GC 后,survivor 区空间不能容纳全部存活对象;
G1 垃圾回收器包含两个阶段,G1会在这两个阶段循环:
- Young-only phase: 首先年轻代执行Normal类型垃圾回收,并不断提升对象到老年代,当老年代占用达到the Initiating Heap Occupancy threshold后,G1开启Concurrent Start垃圾回收,这两个阶段不会STW,接下来的Remark和Clean动作真正执行清理工作,会STW
- Space Reclamation phase: 该阶段包含多种 Mixed 垃圾回收(包含年轻代垃圾回收),会清理老年代对象。
作为兜底,如果G1发现堆内存不够用时会触发Full GC。
- Remember Set : 当前Region使用 Remember Set 记录其他Region到当前Region的引用,当前Region发生GC时,这些引用需要更新指向。
- Collection Set : 待回收Region集合
参考: Garbage-First Garbage Collector
参数配置
G1 GC需要配置参数:-XX:+UseG1GC
开启
堆内存配置
1
| -Xms8G -Xmx8G -Xss512K -XX:+UnlockExperimentalVMOptions -XX:G1MaxNewSizePercent=40
|
配置 | 说明 | 建议 |
---|
-Xms8G | 堆内存最小值 | 一般为pod内存的80% |
-Xmx8G | 堆内存最大值 | 一般为pod内存的80% |
-Xss512K | 线程栈大小,默认1M | 512K或1M |
-XX:G1NewSizePercent=30 | 年轻代占整个堆的比例最小值 (需开启-XX:+UnlockExperimentalVMOptions) | 对于启动pod时获取缓存的场景, 可适当调大, 减少启动阶段的频繁调整 |
-XX:G1MaxNewSizePercent=40 | 年轻代占整个堆已使用的比例最大值 (需开启-XX:+UnlockExperimentalVMOptions) | 大堆建议调小阈值(>=32G), 降低单次年轻代回收的STW时间 |
-XX:G1HeapRegionSize=4M | G1 Region的大小. 值是 2 的幂, 范围是 1 MB 到 32 MB 之间 | 小堆且常态有持续大对象产生的场景, 可适当调大 |
关于Region Size可参考:
Heap Size | Region Size |
---|
heap < 4GB | 1MB |
4GB <= heap < 8GB | 2MB |
16GB <= heap < 32GB | 8MB |
32GB <= heap < 64GB | 16MB |
64GB <= heap | 32MB |
GC配置
1
| -XX:+UseG1GC -XX:MaxGCPauseMillis=100 -XX:InitiatingHeapOccupancyPercent=50 -XX:MaxTenuringThreshold=10
|
配置 | 说明 | 建议 |
---|
-XX:+UseG1GC | 开启G1垃圾回收 | |
-XX:MaxGCPauseMillis=100 | 预期GC STW时间,单位ms | 看场景,低时延的可配置到100ms以内,最大不超过500ms |
-XX:InitiatingHeapOccupancyPercent=50 | 触发GC标记周期的堆占用百分比 | 大堆(>=32GB)时适当调大阈值, 减少标记触发 |
-XX:G1HeapWastePercent=10 | 默认值 : 10% , 堆浪费百分比, 当G1发现可被回收的空间小于10%时, 就不会再进行混合收集, 也就是会结束当前的混合收集周期 | |
-XX:G1OldCSetRegionThresholdPercent=10 | 默认值 : 堆的5%, 设置混合垃圾回收期间要回收的最大旧区域数占整个堆的百分比 | |
-XX:G1MixedGCLiveThresholdPercent=70 | 默认值 : 65%, MixGC时, 年老代Region中存活对象百分比, 只有在此阈值下的Region才会被选入回收列表CSet (需开启-XX: +UnlockExperimentalVMOptions ) | 大堆(>=32GB)时适当调大阈值, 增加扫描年老带Region的备选集合, 增加年老代回收效率 |
-XX:G1MixedGCCountTarget=8 | 最多8次混合垃圾回收, 设置标记周期完成后, 对存活数据上限为 G1MixedGCLIveThresholdPercent 的旧区域执行混合垃圾回收的目标次数 | |
-XX:MaxTenuringThreshold=n | 默认值15, 对象进入年老带前在Survivor区中的最大存活年龄 | survivor区过大时, 可以跟进GC Log分析分代存活分布, 适当调小阈值, 减轻复制压力, 让对象快速进入年老代,降低young gc压力. |
NMT
1
| -XX:NativeMemoryTracking=detail
|
配置 | 说明 | 建议 |
---|
-XX:NativeMemoryTracking | 默认值 : 关闭 [summary/detail] , 用于堆外内存泄露分析 | |
GC日志配置
1
2
3
4
| // Java8:
-XX:+PrintGCCause -XX:+PrintGCDetails -XX:+PrintGCApplicationStoppedTime -XX:+PrintAdaptiveSizePolicy -XX:+PrintTenuringDistribution -XX:+PrintReferenceGC -XX:+PrintHeapAtGC -XX:+PrintGCDateStamps -XX:+PrintGCTimeStamps -Xloggc:gc.log -XX:+UseGCLogFileRotation -XX:NumberOfGCLogFiles=5 -XX:GCLogFileSize=2M
// Java11以上:
-Xlog:gc*=info,phases*=debug,region*=debug,age*=trace,ergo*=debug,safepoint,heap*=debug:file=gc.log:time,level,tags:filecount=5,filesize=2m
|
配置 | 说明 | 建议 |
---|
-XX:+PrintGCCause | 打印触发GC的原因 | 默认开启 |
-XX:+PrintGCDetails | 打印GC各阶段详细日志 | 默认开启 |
-XX:+PrintGCApplicationConcurrentTime | 打印GC并行处理时间 | 不开启 |
-XX:+PrintGCApplicationStoppedTime | 打印GC STW时间 | 默认开启 |
-XX:+PrintAdaptiveSizePolicy | 打印自适应分代调整信息 | 默认开启 |
-XX:+PrintTenuringDistribution | 打印GC扫描存活对象年龄分布 | 默认开启 |
-XX:+PrintReferenceGC | 打印引用GC处理详情 | 默认开启 |
-XX:+PrintGCDateStamps | 打印GC绝对日期, 默认为从JVM开始的相对时间戳 | 默认开启 |
-XX:+PrintGCTimeStamps | 打印GC绝对时间, 默认为从JVM开始的相对时间戳 | 默认开启 |
-XX:+PrintHeapAtGC | 打印GC前后堆内存详情 | 默认开启 |
其他
配置 | 说明 | 建议 |
---|
-XX:-UseBiasedLocking | 默认值 : 偏向锁开启。当锁竞争不激烈时可以通过偏向来提高性能. 但是高并发的情况下, 偏向锁会经常失效, 取消偏向锁时, 需要获取每个线程使用锁的状态以及运行状态,该过程会STW | |
-XX:-OmitStackTraceInFastThrow | 默认值 : 开启 | 同一位置不断抛出同样的Exception, JIT会丢弃原始堆栈和Message来提升性能. 无脑关闭 |
配置参考
规格实例 | 配置参数 |
---|
1C2G | -Xmx1G -Xms1G -Xss256K -XX:MaxMetaspaceSize=320M -XX:MetaspaceSize=320M -XX:+UseG1GC -XX:MaxGCPauseMillis=100 -XX:ParallelGCThreads=1 -XX:ConcGCThreads=1 -XX:InitiatingHeapOccupancyPercent=50 -XX:-OmitStackTraceInFastThrow -XX:+ParallelRefProcEnabled -XX:+PrintGCDetails -XX:+PrintGCDateStamps |
4C8G | -Xmx6G -Xms6G -Xss512K -XX:MaxMetaspaceSize=320M -XX:MetaspaceSize=320M -XX:+UseG1GC -XX:MaxGCPauseMillis=100 -XX:ParallelGCThreads=4 -XX:ConcGCThreads=1 -XX:InitiatingHeapOccupancyPercent=50 -XX:-OmitStackTraceInFastThrow -XX:+ParallelRefProcEnabled -XX:+PrintGCDetails -XX:+PrintGCDateStamps |
8C16G | -Xmx12G -Xms12G -Xss512K -XX:MaxMetaspaceSize=320M -XX:MetaspaceSize=320M -XX:+UseG1GC -XX:MaxGCPauseMillis=100 -XX:ParallelGCThreads=8 -XX:ConcGCThreads=2 -XX:InitiatingHeapOccupancyPercent=40 -XX:-OmitStackTraceInFastThrow -XX:+ParallelRefProcEnabled -XX:+PrintGCDetails -XX:+PrintGCDateStamps |