分享一次cpu98%的问题排查

1.第一步 执行top,很明显pid是1的进程的cpu占用特别高

分享一次cpu98%的问题排查_第1张图片

 

 

2.第二步 执行top -Hp 1,查看到进程1下面的pid是8,9,10,11这四个线程的cpu占用比较异常

对应java程序里的tid是0x8 0x9 0xa 0xb。

分享一次cpu98%的问题排查_第2张图片

3.第三步执行jstack 1 > 20191107.log 获取到日志文件,查到刚好是垃圾回收的几个线程

分享一次cpu98%的问题排查_第3张图片

 

4.第四步再执行jstat -gcutil 1 2000

分享一次cpu98%的问题排查_第4张图片

发现FGC很频繁,而且有没次fgc的效率不高,就算回收了还是暂用97、98%,说明有大量的老年代对象没有被回收

5.第五步,是什么原因导致老年代对象没有被回收呢,首先我们先执行java -XX:+PrintCommandLineFlags -version

查看jvm的堆参数配置以及垃圾回收器

最大堆内存大小是2G 左右,垃圾回收是ParallelGC 并行垃圾回收器

newRatio 等于2,老年代,占比2/3,4/3g * 98% = 1.306g的老年代堆内存一直不能被回收。

6.第六步,执行jmap -dump:format=b,file=20191029.dump 1,生成dump文件,使用visualVm工具打开dump文件,

分享一次cpu98%的问题排查_第5张图片

分析发现有很多boundSql占用了大量的内存,并且不能被释放,这条sql是updateBatchById,查询数据库,

这条sql一直被占用,并且不会被释放。查阅代码,发现有一条批量更新语句,使用case id  when  then 的语法,这条批量更新语句更新大概2w行数据,导致数据库SQL语句执行缓慢,e其实是固定的,没有必要这样写sql。后修改SQL 为updat a set  a.c = d where e = xxx,重新部署,运行一段时间,服务器的cpu一直正常。

你可能感兴趣的:(JMM)