这次是对于JDK7以后的GC的一个补充
那么GC的调优思路是什么?
我们首先看,可以分为内存占用,延迟,吞吐量
那么我么你的思路就是
1.现对于响应的时间和业务量的保证,然后控制GC的暂停时间,保证必要的吞吐量
2.掌握JVM和GC的状态,定位具体的问题,确定是否有GC调优的必要,利用jstat进行查看GC状态,开启GC日志,利用操作系统的诊断工具,追踪GC日志
3.判断GC类型是否是需要调优的类型,是哪个部分的GC出现了问题,是MinorGC长,还是Mixed GC 异常停顿
4.分析并调整具体的软硬件的配置
5.验证调优的目标,如果达到了目标,结束调优,不然就while循环
我们先说下的是新JDK的G1的流程
G1的内存布局,是棋盘状的一个个region组成的,示意图如下
region的大小是一致的,数值在1M到32M之间的一个2的幂等数,JVM会尽量的分为2048个,同等大小的region,数字可以手动调整
G1中因此没有年代的实际概念,年代只是一个逻辑的概念,一部分region是作为Eden,一部分作为Survivor,除此外,G1中还有一个特殊的对象,Humongous对象,放在Humongous中,逻辑上,Humongous region算是老年代的一部分,但是大对象不适合复制,所以单另出来了
而且,因为Humongous的存在,可能超过一个region的大小,所以可能在分配大对象的时候难以找到连续空间,不过可以考虑设置更大的region大小
-XX:G1HeapRegionSize=<N
GC算法方面,G1使用的是符合算法
新生代,G1使用的是并行的复制算法,会有Stop-The-World的暂停
老年代,大部分都是并发标记,整理则是新生代GC捎带着的,而且并不是整体的整理,而是增量进行
对于G1,减少了Major GC的概念,
Minor GC仍然存在,但是老年代的回收,依靠了Mixed GC,并发结束后,JVM就可以垃圾收集,但是Mixed GC会清除新生代外,还会清理部分已经标记的老年代,
清理老年代的数据的比例,可以通过接口设置
–XX:G1MixedGCLiveThresholdPercent
–XX:G1OldCSetRegionThresholdPercent
G1的概念中包含了一个重点,Remembered Set,记录Region之间的对象引用,因为GC是复制算法,复制算法就是从Eden Survivor的移动,所以必须要保证跨区引用有效,所以,Remembered Sets记录了引用
但是Remembered Set,需要占用额外的空间,可能占用Heap的20%到更高,而且进行对象复制的时候,需要扫描和更改Card Table的信息,影响了暂停时间
关于G1的行为变化,还有一些,这里主要放本书 Java Performance Companion
还有对于G1的 Humongous region 作为老年代的一部分,在老版的JDK中,是在并发标记结束后进行,但是新版的JDK中,Humongous对象的回收采用了更加基金的策略,因为老年代的对象比较少,所以可以维护一个老年代是否引用的队列,这样,新生代GC的时候,也能知道是否可以收集Humongous,所以,对于Humongous的回收,就是在Young GC确定无引用的时候
而且,对于字符串的排重, G1会把新创建的字符串对象放入队列 young GC的时候,就会并发的时候将内部数据一致的字符串进行排重,引用到一个数组
激活参数是
-XX:+UseStringDeduplication
还有就是类型卸载,是一个长期困扰Java的问题,Java中,原本只有加载其的自定义类加载器卸载的时候,才能被卸载
G1对于类型加载有什么改进呢?G1早期版本是只有Full GC类型才能卸载
对于 类型卸载的查看,可以加入如下的参数 -XX:+TraceClassUnloading
但是后来,加入如下的选项
-XX: +ClassUnloadingWithConcurrentMark
在并发标记阶段接收后,JVM会进行类型卸载
老年代的回收,基本要等待并发标记结束就可以,但是如果堆满的时候,还能回收完成,会触发Full GC,所以触发并发标记很重要,早期的G1调优中会设置一个触发阈值的参数
-XX:InitiatingHeapOccupancyPercent
JDK9之后,这个参数只会作为一个初始值,在运行的时候采样,获取统计数据,然后动态调整启动时机,默认开启了一个JVM参数
-XX: +G1UseAdaptiveIHOP
对于JDK的调优的一个思路,简单的就是升级到新的JDK版本
新JDK必然带来性能上提升
然后对于开始的日志收集,我们可以通过参数设置打开GC 日志
-XX: +PrintGCDetails
-XX: +PrintGCDateStamps
还可以打印G1, Ergonomics相关信息
-XX:+PrintAdaptiveSizePolicy
G1中,Ergonomics就是查看Humongous的分配,通过这个可以查看增大堆的大小,直接将region大小提高
对于GC的延迟问题,可以开启如下的参数
-XX: +PrintReferenceGC
还可以看引用处理
-XX: +ParallelRefProcEnabled
在JDK9之后,JVM和GC就对日志机构进行重构,PrintGCDetails已经标记为了废弃
PrintGCDateStamps已经移除,指定开启会导致JVM无法启动
java -Xlog:help
我们对于G1进行了内部结构和机制还能调优
如果发生Young GC非常耗时,可以调整新生代的大小,减小新生代的最小比例
-XX:G1NewSizePercent
降低其最大值对降低Young GC延迟有帮助
-XX:G1MaxNewSizePercent
G1设置较小的延迟目标,这会导致减小新生代的效果
如果Mixed GC比较长
可以减少一次性处理的region个数
或者介绍了G1OldCSetRegionThresholdPercent控制最大值,可以提高Mixed GC的个数,
个数越多,单次被包含的region就减少
-XX: G1MixedGCountTarget