GC 调优的目标
GC 调优一般是为了:
- 降低内存占用
- 降低延迟
- 增加吞吐量
当然,很难三者都兼顾;一般只能侧重其中一两个。
有时候 GC 参数不合理会导致 OOM,这时候也需要调优。
GC 调优的一般思路
1. 根据实际应用场景确定调优目标
如,GC 停顿时间不能大于200ms,同时吞吐量不能低于每秒 1W 次请求。
所以 GC 调优是非常考验个人技术经验的。如果没有丰富的实践经验作为决策依据,很可能会出一些“拍脑袋”的不现实目标。
2. 分析 JVM 中 GC 的状态,定位问题原因,以确定是否有调优的必要
一般可以通过 jstat 等JVM监控工具、GC日志、操作系统诊断工具等获取JVM相关信息。
如,发现应用在某段时间响应很慢时,可以查看这段时间的GC日志,是否有GC导致长时间的停顿。
也得区分是 Minor GC 耗时过长,还是 Mixed GC 耗时过长。
3. 确定使用哪种 GC
如果应用系统当前所使用的 GC 不符合应用服务特征,就得更换GC。
如,CMS 和 G1 都是更侧重于 低延迟 的GC;Parallel GC 是侧重于 吞吐量 的GC。
如果当前 GC 符合应用特征,那就得考虑更深入的配置调优。
4. 根据实际情况调整相关 JVM 参数或其它软硬件配置
5. 验证调整后的应用已满足目标
如果已达到目标,则结束调优;如果不满足则需重复分析、调整并验证
GC 调优的一般原则
尽量升级到新的 JDK
很多JVM相关问题,在新的 JDK 已经修复或避免。通常而言,升级 JDK 是最好的解决方案。
很多软件组织名为“以稳定为主,保障安全”,实为“缺乏技术能力,缺乏担当”,所以迟迟不升级 JDK。害了不少人。
做好 GC 相关信息的收集
利用 JVM 参数可以获得 GC 相关信息
- -XX:+PrintGCDetails
- JDK 9 中,该选项已被标记为废弃
- 从 JDK 9 开始,可以用 -Xlog:gc 指定相关 GC 日志的记录方式
- 如,指定记录 trace 级别的 GC 日志,日志文件名为 gc.txt,日志文件数最多6个,每个日志文件最大1MB:
- -Xlog:gc=trace:file=gc.txt::filecount=5,filesize=1m
- 6个日志文件:gc.txt、gc.txt.0、gc.txt.1、gc.txt.2、gc.txt.3、gc.txt.4
- 另,可用 java -Xlog:help 查看更多 JVM 日志选项
- 如,指定记录 trace 级别的 GC 日志,日志文件名为 gc.txt,日志文件数最多6个,每个日志文件最大1MB:
- -XX:+PrintGCDateStamps
- JDK 9 中,该选项已被移除;可以使用 -Xlog:gc
- -XX:+PrintAdaptiveSizePolicy
- GC 的某些行为是根据运行时情况适应性触发的。通过查看该参数相关功能返回的GC信息,有助于我们理解为什么GC出现了我们不希望发生的操作。
- -XX:+PrintReferenceGC
- 如果怀疑引用清理不及时,通过这些信息可以发现哪里出现了堆积情况
- JDK 9 开始,可以用 -Xlog:gc+ref
- 另外,可以通过 -XX:+ParallelRefProcEnabled 开启对引用的并行处理