jvm问题排查一直没有自己的思路体系,这次测试环境发现了一个cpu飙高的问题,刚好用来实践一次,纸上得来终觉浅,绝知此事要躬行。最后捋一下思路和过程,记录

定位java进程

linux, top 命令,发现 23071进程cpu,内存均占比很高

Java oom排查 jvm排查案例_Java oom排查

排查cpu问题,对于jvm如何排查cpu占用?当然是要找到具体的内部线程

查看进程内的线程资源占用

使用命令,top -Hp 23071,

Java oom排查 jvm排查案例_Java oom排查_02

发现这些线程cpu占用很高,想要知道这些线程的信息,则必须借助jstack命令,而jstack中的线程号是十六进制的,故需将线程号转为16进制的,以线程23081为例

使用命令 printf "%x\n" 23081,得到结果 5a29,下一步则是使用jstack命令查询线程详细信息

定位jvm线程信息

使用命令,jstack 23071 > 23071.txt,将信息输出

查找 5a29的线程信息

Java oom排查 jvm排查案例_Java oom排查_03

线程cpu飙高原因排查

结果,这是一个cms垃圾回收线程,其他的23082,23083也是5a2a等垃圾回收进程,说明jvm在进行频繁的垃圾回收,内存出问题了(前面已经说了,废话)

GC情况查看

如何查看gc情况?当然是jstat

使用命令jstat -gc 23071

Java oom排查 jvm排查案例_老年代_04

注意FGC 5757次,事件2977.424秒(各个参数的含义和单位可以百度),每次回收0.5s这个已经延迟很高了,此java进程启动不到2天,说明老年代有大量对象无法回收,频繁触发fullgc

堆内存问题定位

内存问题,如何看?先看大致的内存使用,当然是jmap命令,注意(这个会jvm暂停,线上慎用,线上怎么办?)

先查看堆使用信息,jmap -heap 23071 > 23071heap.txt

Java oom排查 jvm排查案例_垃圾回收_05

此java进程使用的是cms垃圾回收器,concurrent mark-sweep generation,代表的是老年代,说明有大量的老年代对象无法回收,下一步则是查看那些对象一直无法回收

还是使用jmap -histo:live 23071 > 23071map.txt,SensorData对象示例一千多万个,定位到此处,应该去排查对应的程序逻辑了。

Java oom排查 jvm排查案例_垃圾回收_06

体会

1.jvm就像个黑箱子,我们发现问题时,需要借助系统命令、jvm工具命令去不停的刺探,按图索骥发现最终的原因,

2.排查次数多了,自己对jvm问题排查的方法和体系就自动建立了