一个应用程序卡死了,查看JVM内存耗尽了,该做些什么呢?
(1)整体资源查看
top命令,查看内存、CPU使用情况是否有明显问题。
(2)查看网络连接数
netstat -an | wc -l
(3)查看内存溢出还是JVM堆内存耗尽
查看OS内存、JVM内存(可通过开启JMX开启JVM监控,用JConsole连接),分析是否存在内存溢出,还是单纯的JVM堆内存耗尽。
(4)查看线程堆栈情况
top -Hp <processID>
查看各个线程中又没有资源使用高的,对于高的,查看16进制的threadID
printf '%x\n' <threadID>
jstack <processID> | grep <16进制的threadID> [-C20] [--color]
其中16进制的threadID为0x开头的线程id,-C20 --color表示显示上下20行,彩色显示threadID
这样就看到了要查找堆栈的堆栈情况。
线程情况可以有BLOCKED ,原因new Connection waiting to lock之类。
可以从堆栈蛛丝马迹分析代码逻辑。
(5)查看dump文件
jmap -dump:format=b,file=XXX.dump <pid>
之后使用IBM Heapanalyzer或JProfile等查看什么对象占了jvm内存。
这个往往是发现问题的关键。
(6)查看GC情况
jstat -gc <pid>查看GC耗时,查看GC日志。
比如看到 Full GC (Metadata GC Threshold),这就是MetaspaceSize 大小不够,JDK8中,XX:MaxMetaspaceSize确实是没有上限的,最大容量与机器的内存有关;但是XX:MetaspaceSize是有一个默认值的:21M,需要调大。