线上GC调优知识点总结

当线上Java程序性能逐渐下降,通过一系列优化手段也提升有限时,通常需要调整垃圾回收器来进一步提高性能,称为GC优化。影响GC性能的参数众多,且参数调整又依赖于应用各自的特点,这些因素很大程度上增加了GC优化的难度,本文介绍了线上GC调试你不得不需要学习的知识点。

1. Java运行参数设置及优化

Java运行时数据区如图所示:

image

我们常说的GC大部分指的是Java Heap的一系列操作。本文的所有操作,是基于jdk1.8版本的。

1.1 堆参数

  • -Xms,堆的初始值,等价于-XX:InitialHeapSize,比如-Xms512m表示初始堆大小为512Mb,-Xms4g表示初始堆大小4g;
  • -Xmx,堆的最大值,等价于 -XX:MaxHeapSize,-Xmx8g表示最大堆为8g;
  • -Xmn,新生代及年轻代大小,则老年代的大小=Xmx-Xmn;
  • -XX:SurvivorRatio,年轻代中Eden区所占比例,默认是8,也就是Eden默认占80%;

最好将 -Xms 和 -Xmx 的值设置成一样的值,这样做是为了防止随着堆空间使用量增加,会动态的调整堆空间大小,有一定的性能损耗,不如开始就设置成相同的值,来规避性能损失。

1.2 栈参数

  • -Xss,栈空间大小,栈是线程独占的,所以是一个线程使用栈空间的大小,默认值是1M;

Each thread in a Java application has its own stack. The stack is used to hold return addresses, function/method call arguments, etc. So if a thread tends to process large structures via recursive algorithms, it may need a large stack for all those return addresses and such. With the Sun JVM, you can set that size via that parameter.

1.3 Metaspace参数

  • -XX:MetaspaceSize,Metaspace空间初始大小,默认是20.79M,这个初始大小是触发首次Metaspace Full GC的阈值,配置案例如 -XX:MetaspaceSize=256M;
  • -XX:MaxMetaspaceSize,Metaspace 最大值,默认不限制大小;
  • -XX:MinMetaspaceFreeRatio,最小空闲比,当Metaspace发生GC后,会计算Metaspace 的空闲比,如果空闲比(空闲空间/当前Metaspace大小)小于此值,就会触发Metaspace扩容。默认值是40 ,也就是40%,配置案例如 -XX:MinMetaspaceFreeRatio=40;
  • -XX:MaxMetaspaceFreeRatio,最大空闲比,当Metaspace发生GC后,会计算Metaspace的空闲比,如果空闲比(空闲空间/当前Metaspace大小)大于此值,就会触发Metaspace释放空间。默认值是70 ,也就是70%,配置案例如 -XX:MaxMetaspaceFreeRatio=70;

1.4 JVM运行配置参数

  • -verbose:gc或-XX:+PrintGC,简单输出GC日志;
  • -Xloggc:/logs/gc.log,GC日志输出位置;
  • -XX:+PrintGCDetails,输出GC详细日志;
  • -XX:+PrintGCDateStamps,输出GC的时间戳,以日期的形式,如2020-03-11T17:22:48.180+0800;
  • -XX:+PrintGCTimeStamps,输出GC的时间戳;
  • -XX:+PrintHeapAtGC,在进行GC的前后打印出堆的信息;
  • -XX:+PrintGCApplicationStoppedTime,打印GC导致的Stop The World时间;
  • -XX:+PrintClassHistogramBeforeFullGCXX:+PrintClassHistogramAfterFullGC,GC前后的类加载情况;
  • -XX:+HeapDumpOnOutOfMemoryError,内存溢出时自动导出,内存很大的时候,可能会导不出来,使用XX:HeapDumpPath=dir导出内存映像文件;

1.5 设置垃圾回收器

JDK8可使用的垃圾收集器有7种,当然有的只适用于年轻代,有的只适用于老年代,JDK8中最新的垃圾收集器是G1,可以用于年轻代和老年代。到了JDK 11,还出了ZGC。在JDK8中,如果不指定垃圾收集器,默认使用参数 -XX:+UseParallelGC,新生代使用Parallel Scavenge,老年代使用Serial Old。

  • -XX:+UseParallelGC,Parallel Scavenge + Serial Old,JDK8 server 模式下的默认设置;
  • -XX:+UseParallelOldGC,Parallel Scavenge + Parallel Old;
  • -XX:+UseG1GC,使用G1垃圾收集器

1.6 远程JMX设置

当我们需要查看JVM运行状态,第一种是登陆JVM服务器,使用jmap、jstack、jstat等工具查看;第二种是开启JMX远程功能,使用jConsole、VisualVM等工具进行监控。开启的参数如下:

1
2
3
4
5
6
7
8
-Dcom.sun.management.jmxremote
#指定jvm所在服务器ip或域名
-Djava.rmi.server.hostname=192.168.1.1
#指定端口
-Dcom.sun.management.jmxremote.port=9999
-Dcom.sun.management.jmxremote.rmi.port=9999
-Dcom.sun.management.jmxremote.authenticate=false
-Dcom.sun.management.jmxremote.ssl=false

2. GC日志分析及jstat使用

2.1 Young GC日志

一段典型的Young GC(Minor GC)的日志如下:

1
2020-03-11T17:43:28.034+0800: 20595.056: [GC (Allocation Failure) [PSYoungGen: 4185120K->4923K(4188160K)] 4547662K->368154K(8382464K), 0.0071567 secs] [Times: user=0.13 sys=0.00, real=0.01 secs]

Young GC说明图示:

image

2.2 Full GC日志

Full GC日志:

1
2018-01-10T16:53:43.811+0800: 980.825: [Full GC (Metadata GC Threshold) [PSYoungGen: 21613K->0K(231424K)] [ParOldGen: 390439K->400478K(761856K)] 412053K->400478K(993280K), [Metaspace: 314108K->313262K(1458176K)], 1.2320834 secs] [Times: user=7.86 sys=0.06, real=1.23 secs]

Full GC说明图示:

image

2.3 GC日志分析工具

GChisto,是一款专业分析gc日志的工具,可以通过gc日志来分析:Minor GC、full gc的时间、频率等等,通过列表、报表、图表等不同的形式来反应gc的情况:

image

GC Easy是一款在线的GC日志分析工具,将gc的log上传后,直接查看结果:

image
image

2.4 jstat使用

jstat是Java提供的查看JVM统计信息的工具,jstat的命令格式为:

1
2
3
4
5
6
jstat [options] pid [interval] [count]
options,一般使用 -gcutil 或 -gc 查看gc情况
pid,当前运行的Java进程号
interval,间隔时间,单位为秒或者毫秒
count,打印次数,如果缺省则打印无数次

options参数如下:

1
2
3
4
5
6
7
8
9
10
11
-gc:统计 jdk gc时 heap信息,以使用空间字节数表示
-gcutil:统计 gc时 heap情况,以使用空间的百分比表示
-class:统计 class loader行为信息
-compile:统计编译行为信息
-gccapacity:统计不同 generations(新生代,老年代,持久代)的容量使用的最大最小值,例如使用到的最大值、最小值、当前使用值等等
-gccause:统计引起 gc的事件
-gcnew:统计 gc时,新生代的情况
-gcnewcapacity:统计 gc时,新生代 heap容量
-gcold:统计 gc时,老年代的情况
-gcoldcapacity:统计 gc时,老年代 heap容量
-gcpermcapacity:统计 gc时, permanent区 heap容量

以jstat -gc 60067 10000 5命令为例,运行结果为:

image

每一列的含义为:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
S0C: 第1个Survivor空间的容量 Current survivor space 0 capacity (kB).
S1C: 第2个Survivor空间的容量(kB).
S0U: 第1个Survivor空间中已经使用的容量 Survivor space 0 utilization (kB).
S1U: 第2个Survivor空间中已经使用的容量(kB).
EC: Eden空间的容量(kB).
EU: Eden空间中已经使用的容量(kB).
OC: 老年代Old空间的容量(kB).
OU: 老年代Old空间已经使用的容量(kB).
MC: 元空间Metaspace的容量(kB).
MU: 元空间Metaspace已经使用的容量(kB).
CCSC: 压缩类空间的容量 Compressed class space capacity (kB).
CCSU: 压缩类空间已经使用的容量(kB).
YGC: Young GC发生的次数.
YGCT: Young GC花费的时间.
FGC: Full GC发生的次数.
FGCT: Full GC花费的时间.
GCT: 所有的GC花费的总时间.

以上内容就是关于线上GC调优知识点总结的全部内容了,谢谢你阅读到了这里!

Author:zhaoyh