最近碰到几次java应用某台机器cpu比较高的情况,而且重启后基本上都会恢复正常。
正常情况下:
应用使用CPU在 :30%--40%
异常情况下:
CPU利用率在:80%---90%
在网上查了下,一般java应用cpu过高基本上是因为
1.程序计算比较密集
2.程序死循环
3.程序逻请求堵塞
分析步骤:
1.登陆应用机器,top命令查看 当前占用cpu资源最多的,一般排名第一位肯定是java进程
一般也可能存在多个java进程
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
17766 nobody 20 0 5818m 2.4g 14m S 51.8 65.2 144:09.75 java
2.查看进程的哪个线程占用cpu比较高
取线上另外一台正常情况下利用cpu比较高的应用:通过
ps -mp PID号 -o THREAD,tid,time
可以可看到线程ID和线程使用的时间。。。
# ps -mp 18429 -o THREAD,tid,time
USER %CPU PRI SCNT WCHAN USER SYSTEM TID TIME
spider 93.8 - - - - - - 5-21:06:57
spider 0.0 19 - futex_ - - 18429 00:00:00
spider 93.7 19 - - - - 18430 5-21:01:16
spider 0.0 19 - futex_ - - 18431 00:00:10
TID为18430的线程利用cpu资源比较多,怎么能看到这个线程在干什么呢?
需要将18430转换为16进制,便于在jvm堆栈中查找。
printf "%x\n" 18430
通过jstack命令来查看下当前内存状态:
#sudo -u nobody jstack 18429 |grep 47fe -A 60 |less (或者切换到java程序运行的账户)
"main" prio=10 tid=0x00002aff38005800 nid=0x47fe runnable [0x00002aff35db4000]
java.lang.Thread.State: RUNNABLE
at java.net.PlainSocketImpl.socketAvailable(Native Method)
at java.net.PlainSocketImpl.available(PlainSocketImpl.java:472)
- locked <0x00000007434484b0> (a java.net.SocksSocketImpl)
at java.net.SocketInputStream.available(SocketInputStream.java:217)
at com.mysql.jdbc.util.ReadAheadInputStream.available(ReadAheadInputStream.java:231)
at com.mysql.jdbc.MysqlIO.clearInputStream(MysqlIO.java:940)
剩下的事情,如果是自己写的代码就很好办了。
如果是有对应开发人员,接下来就是找开发人员确认这段代码是否可以优化。