对于java应用如存在CPU使用100%,该如何定位问题?
以下以模拟示例介绍定位思路。
(一)模拟环境
(1)Redhat_68x64
(2)JDK1.8.0
(3)eclipse编写模拟程序
- 编写模拟CPU使用100%java程序,如下图所示:
package cpu100test;
//模拟CPU使用100%示例来源:https://blog.csdn.net/wsjtwmy/article/details/103526344
public class cpu100test {
public static void main(String[] args) {
int num = 12;
Thread[] threads = new Thread[num];
for (int i = 0; i < num; i++) {
threads[i] = new Thread(new PressureRunner());
threads[i].start();
}
}
public static class PressureRunner implements Runnable {
@Override
public void run() {
while (true) {
}
}
}
}
右键导出可运行的jar包。
运行jar文件,模拟CPU运行100%。
(4)使用top查看运行该java程序机器CPU使用情况,可以看到CPU使用已经100%,java使用最高,进程PID为2396
(5)查看PID :2396内部线程情况,使用top -Hp 2396
可以看到占用最高的线程id为2427,转化为十六进制,使用命令:printf "%x\n" 2427。
(6)打印堆栈信息:jstack 2396 |grep 97b
可以看到对应java内的线程(tid)为0x00007f00b4288000,操作系统级别线程(nid)为0x97b
备注:
jstack命令相关参数解释
tid: java内的线程id
nid: 操作系统级别线程的线程id
prio: java内定义的线程的优先级
os_prio:操作系统级别的优先级
根据上面的堆栈信息就可以找到具体代码。
(7)下面使用jstack打印堆栈信息并输出文件。使用命令:jstack -l 2396>test.out
(8)使用文本编辑器查看test.out文件,可以看到上图打印堆栈信息,对应的更详细的代码,发现cpu100test.java文件中第16行存在问题。
即定位到源代码文件中的以下位置。
或者直接使用命令jstack 2396 | grep 97b -A 30
因上次查看进程2396时使用输出堆栈文件,未直接使用命令,下面截图是使用新的进程2984打印的,所以和上面的堆栈信息不一致,请注意,理解意思即可。
附:jstack命令详解
-F:当正常输出的请求不被响应时,强制输出线程堆栈。
-l:除堆栈外,会打印出额外的锁信息,在发生死锁时可以用jstack -l pid来观察锁持有情况
-m:如果调用到本地方法的话,可以显示C/C++的堆栈