当线上Java程序性能逐渐下降,通过一系列优化手段也提升有限时,通常需要调整垃圾回收器来进一步提高性能,称为GC优化。从性能来说,GC调优主要关注以下三个评分指标:内存占用、延迟、吞吐量。影响GC性能的参数众多,且参数调整又依赖于应用各自的特点,这些因素很大程度上增加了GC优化的难度,本文介绍了线上GC调优需要学习的一些知识点。
1. Java运行参数设置及优化
Java运行时数据区如图所示:
我们常说的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:+PrintClassHistogramBeforeFullGC和XX:+PrintClassHistogramAfterFullGC,GC前后的类加载情况;
- -XX:+HeapDumpOnOutOfMemoryError,内存溢出时自动导出,内存很大的时候,可能会导不出来,使用XX:HeapDumpPath=dir导出内存映像文件;
1.5 设置垃圾回收器
JDK8可使用的垃圾收集器有7种,当然有的只适用于年轻代,有的只适用于老年代,JDK8中最新的垃圾收集器是G1,可以用于年轻代和老年代,到了JDK11,还出了ZGC。
- -XX:+UseSerialGC,虚拟机Client模式下的默认值,使用Serial(新生代)+ Serial Old(老年代)收集器;
- -XX:+UseParNewGC,使用ParNew + Serial Old,JDK9后不再支持;
- -XX:+UseConcMarkSweepGC,使用ParNew + CMS + Serial Old组合收集器,Serial Old作为CMS出现“Concurrent Mode Failure”错误后的备选;
- -XX:+UseParallelGC,使用Parallel Scavenge(新生代) + Serial Old(老年代)收集器,JDK9之前Server模式下的默认设置;
- -XX:+UseParallelOldGC,使用Parallel Scavenge(新生代) + Parallel Old(老年代)收集器;
- -XX:+UseG1GC,使用G1垃圾收集器,JDK9之后的Server模式默认值;
1.6 远程JMX设置
当我们需要查看JVM运行状态,第一种是登陆JVM服务器,使用jmap、jstack、jstat等工具查看;第二种是开启JMX远程功能,使用jConsole、VisualVM等工具进行监控。开启的参数如下:
1 | -Dcom.sun.management.jmxremote |
2. GC日志分析
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说明图示:
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说明图示:
2.3 GC日志分析工具
GChisto,是一款专业分析gc日志的工具,可以通过gc日志来分析:Minor GC、full gc的时间、频率等等,通过列表、报表、图表等不同的形式来反应gc的情况:
GC Easy是一款在线的GC日志分析工具,将gc的log上传后,直接查看结果:
3. 常用JDK工具
3.1 可视化工具类
工具 | 说明 |
---|---|
jconsole | 用于监控Java虚拟机的使用JMX规范的图形工具。它可以监控本地和远程JVM。它还可以监控和管理应用程序。 |
jvisualvm | 提供内存和CPU分析,堆转储分析,内存泄漏检测等监控。 |
3.2 监控类
jstat是查看JVM统计信息的工具,jstat的命令格式为:
1 | jstat [options] pid [interval] [count] |
options参数如下:
1 | -gc:统计 jdk gc时 heap信息,以使用空间字节数表示 |
以jstat -gc 60067 10000 5命令为例,运行结果为:
每一列的含义为:
1 | S0C: 第1个Survivor空间的容量 Current survivor space 0 capacity (kB). |
jps是进程状态工具(JVM Process Status Tool),在目标系统上列出HotSpot Java虚拟机进程的描述信息。
3.3 故障分析类
工具 | 说明 |
---|---|
jinfo | Java的配置信息工具(Java Configuration Information),用于打印指定Java进程、核心文件或远程调试服务器的配置信息。 |
jhat | Java堆分析工具(Java Heap Analysis Tool),用于分析Java堆内存中的对象信息。 |
jmap | Java内存映射工具(Java Memory Map),主要用于打印指定Java进程、核心文件或远程调试服务器的共享对象内存映射或堆内存细节,打印内存dump文件等。 |
jstack | Java的堆栈跟踪工具,主要用于打印指定Java进程、核心文件或远程调试服务器的Java线程的堆栈跟踪信息。 |
3.4 其他
Arthas是Alibaba开源的Java诊断工具,深受开发者喜爱。支持在线排查程序问题,无需重启,可动态跟踪Java代码,可实时监控JVM状态。支持Linux/Mac/Windows,采用命令行交互模式,同时提供丰富的Tab自动补全功能,进一步方便进行问题的定位和诊断。
4. 参考文档
以上内容就是关于JVM性能及GC调优的全部内容了,谢谢你阅读到了这里!
Author:zhaoyh