JVM实战01(CPU过高)
目录
问题简介
linux线上发生CPU过高情况,如何快速定位是什么原因导致?如何定位哪些热点代码?
一:top + jstack
1.使用top命令查出耗cpu的进程
1.键入:top命令
2.如上图:
当前所有核数总的cpu平均是2.3us
最耗cpu的进程是36032,耗费了30.7%(注意这里是进程消耗)
3.我们要定位热点代码光知道进程不行,还需要定位到该进程哪个线程消耗的多
2.使用top -Hp PID 查出线程的cpu消耗情况
1.键入:top -Hp 36032 //这里的36032是进程
2.如上图当前显示的是所有线程的cpu消耗:
最耗cpu的线程是36044,耗费41.7%
3.查线程的目的是为了搜索进程里的线程信息,精确到代码哪一行。
3.查找36044转成十六进制的值
1.键入: printf %x 36044
输出:8ccc
2.jstack转存的信息是16进制的,所以我们要知道当前最耗的线程转成16进制线程号是多少,
以便于搜索关键字,定位问题。
4.使用jstack查看进程(注意是进程,并且是16进制的)
1.键入:
jstack 36032 > 1.txt // 使用jstack将36032进程的所有信息转存到1.txt文件中(这里是进程级别的)
2.接着键入:
cat 1.txt | grep -A 30 8CCC //搜索8ccc这一行,以及往后30行
3. grep -A 命令
-A -B -C 后面都跟阿拉伯数字
-A是显示匹配后和它后面的n行。
-B是显示匹配行和它前面的n行。
-C是匹配行和它前后各n行。
总体来说,-C覆盖面最大。用它保险些。哈哈。这3个开关都是关于匹配行的上下文的(context)
如上图:
1.8ccc的线程名是"Thread-0"
2.出问题的代码:
HoldCPUTask.run(HoldCPUMain.java:13)
HoldCPUMain类的13行run方法,这里写了测试方法,方法里做了一个while死循环做大量计算,
导致占用cpu过高。
二:JMC远程连接
1.如上图按步骤操作。
2.使用JMC有前提,远程linux机器开启了JMX配置。
点击JMC上方:
文件--->远程连接
三:常见引起cpu过高问题总结
1.无限while循环
。尽量避免
。无法避免,让循环执行慢一点
2.频繁GC
。降低GC频率
3.频繁创建新对象
。合理使用单例
4.序列化和反序列化
。合理使用API
。选择好用的类库
5.正则表达式(使用了一个引擎在进行字符串匹配的时候会进行回溯)
。少用
。改写正则表达式,降低回溯的发生
6.频繁的线程上下文切换
。降低切换的频率