最近碰到几次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)

剩下的事情,如果是自己写的代码就很好办了。

如果是有对应开发人员,接下来就是找开发人员确认这段代码是否可以优化。