服务程序卡死无响应一例
服务端使用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时间,或者报内存不够;
使用分析工具可找到具体的对象;