服务程序卡死无响应一例
服务端使用Springboot编写,在测试时发现服务超时,对数据库进行了检查,无慢SQL,内存使用正常,磁盘使用正常;
使用top查看应用服务器状态,发现Java进程62278占用CPU 700%,通过进程ID,查看对应线程;
[cayy@localhost test]$ top -H -p 62278
top - 10:53:11 up 164 days, 16:13, 4 users, load average: 5.77, 6.06, 6.16
Threads: 46 total, 8 running, 38 sleeping, 0 stopped, 0 zombie
%Cpu(s):100.0 us, 0.0 sy, 0.0 ni, 0.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st
KiB Mem : 12125828 total, 168556 free, 10434352 used, 1522920 buff/cache
KiB Swap: 8257532 total, 7755516 free, 502016 used. 1131656 avail Mem
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
62282 xisoft 20 0 13.8g 8.5g 13388 R 99.9 73.4 27:03.49 java
62280 xisoft 20 0 13.8g 8.5g 13388 R 99.9 73.4 27:03.41 java
62281 xisoft 20 0 13.8g 8.5g 13388 R 99.9 73.4 27:04.16 java
62284 xisoft 20 0 13.8g 8.5g 13388 R 99.9 73.4 27:03.00 java
62285 xisoft 20 0 13.8g 8.5g 13388 R 99.9 73.4 27:03.41 java
62286 xisoft 20 0 13.8g 8.5g 13388 R 99.9 73.4 27:03.37 java
62287 xisoft 20 0 13.8g 8.5g 13388 R 99.9 73.4 27:02.80 java
62283 xisoft 20 0 13.8g 8.5g 13388 R 99.7 73.4 27:03.27 java
62278 xisoft 20 0 13.8g 8.5g 13388 S 0.0 73.4 0:00.00 java
62279 xisoft 20 0 13.8g 8.5g 13388 S 0.0 73.4 0:12.47 java
使用jstack将java线程状况输出到文件
$ jstack 62278 > 62278.txt
转换线程的id到16进制
$ python -c "print hex(62282)"
0xf34a
在jstack输出文件中检索0xf34a
$ cat 62278.txt | grep 0xf34a
"GC task thread#2 (ParallelGC)" os_prio=0 tid=0x00007f7d28062000 nid=0xf34a runnable
发现主要线程花费在GC上面,这种情况一般都是有大量对象的创建,甚至瞬时好几百万;使用jmap查使用情况会发现Eden Spaces使用率100%;
$ jmap -heap 62278
具体分析需要对内存进行dump然后用内存工具分析
jmap -dump:format=b,file=62278.dmp 62278
可下载Eclipse的Memory Analyzer或者VisualVM,建议下载最新版本;
https://www.eclipse.org/mat/ https://visualvm.github.io/download.html
注意:由于dump达8GB,所以需要先修改分析工具的配置内存到12G,否则会耗费较长的CPU时间,或者报内存不够;
使用分析工具可找到具体的对象;
