内存爆炸和CPU100%问题分析
当线上的系统突然请求缓慢, CPU100%, 内存占用巨大, 当JVM出现问题时,应该如何排查问题呢
问题排查
登录服务器, 使用
top命令查看系统资源使用情况
一般出问题时java程序的占用是最高的找到CPU或者内存占用高的java进程PID, 使用命令
top -Hp 进程ID, 查询该进程中线程的运行情况使用
printf "%x\n" 线程ID查看线程PID的16进制形式
因为在java日志中记录的PID是16进制的形式jstack 进程ID > ./threadDump.log打印JVM堆栈信息到文件threadDump.log中
在该堆栈信息文件中,找到第3步的线程, 查看具体信息使用
jstat -gcutil 进程号 统计间隔时间 统计次数查看GC的变化情况, 当发现FGC的值一直增大时, 继续使用jmap -heap 进程ID查看进程堆内存的情况, 特别是老年代的使用情况.
老年代内存占用达到阈值时就会触发Full GCjmap -dump:format=b,file=filename 进程ID,导出Java进程下内存堆到文件中, 再把内存镜像dump文件传到本地, 利用工具进行分析
可以使用jhat、VisualVM等工具分析dump文件
原因分析
Full GC次数过多
- jstat命令发现GC次数很多,并且不断增加
- 分析dump文件,查看具体对象的内存占用情况
如果内存占用情况不多, 说明代码中频繁使用了System.gc()
代码中消耗CPU的操作太多
比如复杂的算法,递归的循环等,甚至是代码BUG
锁的使用不正确, 造成死锁
分析JVM堆栈信息,看是否有死锁deadlock
不定期的接口耗时现象
这主要是因为不定期的高并发带来的问题, 要通过压测工具不断加大访问力度, 发现某个接口某个位置响应缓慢, 再查看堆栈日志, 发现大量线程被阻塞在同一位置, 就能查到我们哪个业务代码出了问题