这次是对于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

发表评论

邮箱地址不会被公开。 必填项已用*标注