Skip to the content.

GC调优

常见调优参数

概述

预备知识

查看虚拟机参数命令

java -XX:+PrintFlagsFinal -version | findstr "GC" # windows 下

调优领域

确定目标

科学计算:追求高吞吐量,响应时间长点没事。

互联网项目:响应时间很重要。

低延迟/高吞吐量? 选择合适的 GC

最快的GC是不发生GC

首先排除减少因为自身编写的代码而引发的内存问题

查看 Full GC 前后的内存占用,考虑以下几个问题

新生代调优

内存调优建议从新生代开始。

新生代的特点

新生代内存越大越好么?

幸存区

-XX:MaxTenuringThreshold=threshold 晋升阈值

-XX:+PrintTenuringDistribution 打印信息

Desired survivor size 48286924 bytes, new threshold 10 (max 10) 
- age 1: 28992024 bytes, 28992024 total 
- age 2: 1366864 bytes, 30358888 total 
- age 3: 1425912 bytes, 31784800 total ...

老年代调优

以 CMS 为例

案例

案例 1:Full GC 和 Minor GC 频繁

大量频繁的 GC 说明空间紧张,究竟是那部分空间紧张。如果是新生代的空间紧张,大量的对象被创建,很快就把新生代塞满了。幸存区空间紧张,对象的晋升值减低,很多本来生存周期很短的对象也晋升到老年代去,这样就进一步恶化了。进而触发老年代的 Full GC。

案例 2:请求高峰期发生 Full GC,单次暂停时间特别长(CMS)【业务需求是低延时】

到底是那一部分耗费的时间长?

垃圾回收使用的 CMS。

查看 CMS 的日志,看 CMS 的哪个阶段耗时长。发现重新标记阶段耗时长!

重新标记的时候会扫描整个堆内存(new + old),如果业务高峰,新生代对象比较多,那么扫描时间就很长。在重新标记前先对新生代对象做一次 GC,减少新生代对象的遍历数量。-XX:+CMSScavengeBeforeRemark

回顾 CMS 的几个阶段

案例 3:老年代充裕的情况下,发生 Full GC (CMS jdk1.7)

GC 日志里没有竞争失败,并发失败,碎片过多的错误提示。说明老年代的空间是充裕的。后来发现应用部署在 jdk1.7 里。在 1.7 里,永久代空间的不足也会导致 Full GC,1.8 以后改成了元空间(用的本地内存)不会导致 Full GC。