赞
踩
上一章我们讲解了排查OOM问题的思路和基本操作,这一节,我们接着讲解如何解读垃圾回收(GC)频率、效率等信息
1、首先继续启动我们上一章演示的代码:
java -jar -Xms200M -Xmx200M cpu_oom_demo-0.0.1-SNAPSHOT.jar
2、查看启动的进程pid
jps -l
要查询GC信息,我们可以通过jstat
指令实现
jstat指令的命令格式为:jstat [options] pid [interval] [count]
选项 | 说明 |
---|---|
-gc | 统计垃圾回收的堆信息,单位为空间字节数,即单位为KB |
-gcutil | 统计垃圾回收的堆信息,单位为空间的百分比 |
-class | 统计类加载器的信息 |
-compile | 统计编译行为信息 |
-gccapacity | 统计不同区域(新生代、老年代、永久代)的堆容量信息 |
-gccause | 统计引起垃圾回收的事件 |
-gcnew | 统计垃圾回收时,新生代的情况 |
-gcnewcapacity | 统计垃圾回收时,新生代堆空间容量 |
-gcold | 统计垃圾回收时,老年代的情况 |
-gcoldcapacity | 统计垃圾回收时,老年代堆空间容量 |
-gcpermcapacity | 统计垃圾回收时,永久代的堆空间容量 |
1、统计垃圾回收的堆信息 jstat -gc
每秒统计垃圾回收的堆信息,打印10次,
jstat -gc 1994 1000 10
参数详解:
S0C:第一个幸存区的大小,单位KB
S1C:第二个幸存区的大小
S0U:第一个幸存区的使用大小
S1U:第二个幸存区的使用大小
EC:伊甸园区的大小
EU:伊甸园区的使用大小
OC:老年代大小
OU:老年代使用大小
MC:方法区大小
MU:方法区使用大小
CCSC:压缩类空间大小
CCSU:压缩类空间使用大小
YGC:年轻代垃圾回收次数
YGCT:年轻代垃圾回收消耗时间,单位s
FGC:老年代垃圾回收次数
FGCT:老年代垃圾回收消耗时间,单位s
GCT:垃圾回收消耗总时间
如上所示的java进程,老年代空间大小为133M左右,使用的老老年代空间为6M左右,所以老年代空间充足,再看FGC与YGC,分别为1和4,即老年代回收次数为1,年轻代回收次数为4。消耗还很小,说明目前进程正常。
现在我们来看一个内存溢出的进程信息:
可以看到老年代占用满了,并且GCT垃圾回收时间上升,但是垃圾并没有被回收调,占用依旧拉满,也就是我们常说的垃圾回收不掉信息。
2、查看垃圾回收的空间占比 jstat -gcutil
同时我们也可以利用jstat -gcutil
看看空间占比情况(这里我重新模拟了OOM问题的发生,可以看到内存占比的变化)
jstat -gcutil 1994 1000
参数详解:
S0:幸存1区当前使用比例
S1:幸存2区当前使用比例
E:伊甸园区使用比例
O:老年代使用比例
M:元数据区使用比例
CCS:压缩类使用比例
YGC:年轻代垃圾回收次数
FGC:老年代垃圾回收次数
FGCT:老年代垃圾回收消耗时间
GCT:垃圾回收消耗总时间
可以看到老年代使用比例O,从4.68%逐步飙升到了100%,而垃圾回收时间也从0.034上升到0.710,并且后续显示老年代空间比一直没有下降,说明垃圾没有被回收调,明显出现了内存溢出。
3、统计引起垃圾回收的事件 jstat -gccause
jstat -gccause 1994 1000
参数详解:
S0:幸存1区当前使用比例
S1:幸存2区当前使用比例
E:伊甸园区使用比例
O:老年代使用比例
M:元空间使用比例
CCS:压缩类使用比例
YGC:年轻代垃圾回收次数
YGCT:年轻代垃圾回收所用的时间
FGC:老年代垃圾回收次数
FGCT:老年代垃圾回收所用的时间
GCT:垃圾回收的所用的总时间
LGCC:上次垃圾回收的原因
GCC:当前垃圾回收的原因
如上统计GC日志发现在频繁GC,且GC回收效率一直不高的情况,一是通过上一章讲解的OOM排查思路进行排查内存溢出的原因,二是如果知道了原因,比如是突然上来的用户流量高峰,那么这种也不是代码问题,我们就需要对流量进行限流,或者针对服务器配置进行调整。
比如上述所示,如果发现堆内存不够用了,我们可以调整程序的堆内存:
-Xms
:程序启动时占用的内存大小,此值可以和-Xmx
相同,避免每次垃圾回收后重新分配内存
-Xmx
:程序运行时的最大可占用的内存大小
-Xmn
:年轻代的内存大小,整个堆大小=年轻代 + 老年代,官方建议大小为堆空间的1/3
,年轻代中又细分为伊甸区、幸存1区、幸存2区,其比例默认为8:1:1。如果想要调整伊甸区占年轻代的比例,可以通过-XX:SurvivorRatio=N
来设置,N/(N+2)表示伊甸区的内存占用比例,相对应的幸存区就是1/(N+2)。需要注意的是jdk1.8之后才将持久代与堆隔开,属于物理内存。所以严格意义上来讲,jdk1.8之前,堆大小=年轻代 + 老年代 + 持久代
-XX:NewRatio=N
:表示老年代与年轻代的内存比例,默认为2,即2:1,相当于年轻代占堆内存空间的1/3,老年代占2/3
-XX:PretenureSizeThreshold
:大对象阈值,单位为字节Byte(1M=1024KB, 1KB=1024Byte),如果对象超过这个值,就会直接进入老年代,不会进入年轻代,默认值为0
java -jar -Xms2g -Xmx2g -Xmn512m cpu_oom_demo-0.0.1-SNAPSHOT.jar
本期关于GC信息的查询就到此结束了,下一期我们继续讲解JVM的实操问题
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。