1 确定频繁Full GC现象
jps -l
jstat -gcutil 20954 1000
root@open-api-1:/openapi/2ccm# jstat -gcutil 7551 1000
S0 S1 E O M CCS YGC YGCT FGC FGCT GCT
0.00 100.00 9.00 13.30 95.74 93.97 264 1.745 4 0.783 2.528
0.00 100.00 12.00 13.30 95.74 93.97 264 1.745 4 0.783 2.528
0.00 100.00 12.00 13.30 95.74 93.97 264 1.745 4 0.783 2.528
0.00 100.00 15.00 13.30 95.74 93.97 264 1.745 4 0.783 2.528
jstat执行结果
E,表示Eden
S0、S1,表示Survivor0、Survivor1
O,表示Old
M, 表示元空间
CCS, 表示压缩类空间利用率为百分比
YGC,表示Young GC
FGC,表示Full GC
GCT,表示GC Time
2 找出导致频繁Full GC的原因
分析方法通常有两种:
1)把堆dump下来再用MAT等工具进行分析,但dump堆要花较长的时间,并且文件巨大,再从服务器上拖回本地导入工具,这个过程有些折腾,不到万不得已最好别这么干。
2)更轻量级的在线分析,使用“Java内存影像工具:jmap”生成堆转储快照(一般称为headdump或dump文件)。
jmap命令格式:
jmap [ option ] vmid
使用命令如下:
jmap -histo:live 20954
3 定位到代码
定位带代码,有很多种方法,比如前面提到的通过MAT查看Histogram即可找出是哪块代码。——我以前是使用这个方法。 也可以使用BTrace,我没有使用过。
一台生产环境机器每次运行几天之后就会莫名其妙的宕机,分析日志之后发现在tomcat刚启动的时候内存占用比较少,但是运行个几天之后内存占用越来越大,通过jmap命令可以查询到一些大对象引用没有被及时GC,这里就要求解决内存泄露的问题。
Java的内存泄露多半是因为对象存在无效的引用,对象得不到释放,如果发现Java应用程序占用的内存出现了泄露的迹象,那么我们一般采用下面的步骤分析:
- 用工具生成java应用程序的heap dump(如jmap)
- 使用Java heap分析工具(如MAT),找出内存占用超出预期的嫌疑对象
- 根据情况,分析嫌疑对象和其他对象的引用关系。
- 分析程序的源代码,找出嫌疑对象数量过多的原因
demo
- 获取tomcat的pid
root@open-api-1:/openapi/2ccm# jps -l
7089 open-api-service-mysql-exec.jar
6962 open-api-registry-center-exec.jar
2307 org.apache.catalina.startup.Bootstrap
7156 open-api-service-italy-exec.jar
7396 open-api-service-rabbitmq-exec.jar
12980 open-api-devops-service-exec.jar
13621 sun.tools.jps.Jps
7462 open-api-service-redis-exec.jar
13226 sun.tools.jstatd.Jstatd
7228 open-api-service-finland-exec.jar
7551 open-api-global-quartz-exec.jar
- 利用jmap初步分析内存映射,命令:
root@open-api-1:/openapi/2ccm# jmap -histo:live 7551 | head -100
num #instances #bytes class name
----------------------------------------------
1: 76704 16532752 [C
2: 2061 9877048 [J
3: 61179 1957728 java.util.concurrent.ConcurrentHashMap$Node
4: 20646 1816848 java.lang.reflect.Method
5: 74914 1797936 java.lang.String
6: 11929 1320640 java.lang.Class
7: 19019 1183080 [Ljava.lang.Object;
8: 24605 984200 java.util.LinkedHashMap$Entry
- 如果上面一步还无法定位到关键信息,那么需要拿到heap dump,生成离线文件,做进一步分析,命令:
root@open-api-1:/openapi/2ccm# jmap -dump:live,format=b,file=heap.hprof 7551
Dumping heap to /openapi/2ccm/heap.hprof ...
Heap dump file created
- 拿到heap dump文件,利用MAT来分析heap profile
安装MAT插件(下载https://www.eclipse.org/mat/downloads.php)
解压 右击打开显示包内容
打开MemoryAnalyzer
打开对应的heap.hprof
显示
分析