例如一个java进程的cpu占用达到99.3%
top - 14:56:39 up 199 days, 4:55, 3 users, load average: 2.24, 2.35, 2.27
Tasks: 81 total, 1 running, 76 sleeping, 4 stopped, 0 zombie
%Cpu(s):100.0 us, 0.0 sy, 0.0 ni, 0.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st
KiB Mem : 1883492 total, 100904 free, 968764 used, 813824 buff/cache
KiB Swap: 0 total, 0 free, 0 used. 727152 avail Mem
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
8999 root 20 0 2460600 17060 10116 S 99.3 0.9 31:51.17 java
23996 root 0 -20 138996 17416 6260 S 0.3 0.9 375:12.90 AliYunDun
1 root 20 0 190708 2492 1284 S 0.0 0.1 1:32.14 systemd
2 root 20 0 0 0 0 S 0.0 0.0 0:00.01 kthreadd
3 root 20 0 0 0 0 S 0.0 0.0 0:52.57 ksoftirqd/0
5 root 0 -20 0 0 0 S 0.0 0.0 0:00.00 kworker/0:0H
7 root rt 0 0 0 0 S 0.0 0.0 0:00.00 migration/0
1.top 找到占用cpu太高的java进程的pid 假如是8999
2.查看pid对应进程的线程的资源占用情况
ps -mp 8999 -o THREAD,tid,time
例如
[root@iz8vb3nxwmck3z1ruwn8euz 9000]# ps -mp 8999 -o THREAD,tid,time
USER %CPU PRI SCNT WCHAN USER SYSTEM TID TIME
root 0.0 - - - - - - 00:37:34
root 0.0 19 - futex_ - - 8999 00:00:00
root 0.0 19 - futex_ - - 9000 00:00:05
root 0.0 19 - futex_ - - 9001 00:01:27
假如最高的tid是9000 (线程id)
3.tid转化成十六进制
printf "%x\n" 9000
2328
4.jstack查看线程栈日志 例如
[root@iz8vb3nxwmck3z1ruwn8euz 9000]# jstack 8999 |grep 2328 -A 30
"DestroyJavaVM" #36 prio=5 os_prio=0 tid=0x00007f5e18009800 nid=0x2328 waiting on condition [0x0000000000000000]
java.lang.Thread.State: RUNNABLE
"pool-3-thread-3" #35 prio=5 os_prio=0 tid=0x00007f5dec05b000 nid=0x234c waiting on condition [0x00007f5de59ea000]
java.lang.Thread.State: WAITING (parking)
at sun.misc.Unsafe.park(Native Method)
- parking to wait for <0x00000000f56abee8> (a java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject)
at java.util.concurrent.locks.LockSupport.park(LockSupport.java:175)
at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:2039)
at java.util.concurrent.LinkedBlockingQueue.take(LinkedBlockingQueue.java:442)
at java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1074)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1134)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at java.lang.Thread.run(Thread.java:748)
命中的位置是 nid=0x2328
nid指的是native thread id (linux native light weight process id) 这个日志会显示报错的java代码的那一行。
关于grep里的参数"-A"的说明 -A<显示列数> 除了显示符合范本样式的那一行之外,并显示该行之后的内容。
程序的cpu占用达到80%~100%这种情况,一般可能发送在大量的for循环或者while循环中(也可能是死循环中的反复计算)
demo程序见CpuTest.java
贴出代码
public class CpuTest {
public static void main(String[] args) {
int i= 0;
while (true) {
i++;
// if (i == Integer.MAX_VALUE) {
//// System.out.println("--reset---");
// i = 0;
// }
}
}
}
先编译程序,然后运行CpuTest.class,命令如下
#cd code/
#javac CpuTest.java
#ls
CpuTest.class CpuTest.java
#java CpuTest
然后用top命令可以看到有个java进程cpu占用特别大。