用 top + jstack 定位 java 线程问题

1. 需要定位的程序

首先, 写一个用于计算并输出蜚波那契数列的 java 程序, 大致的输出信息如下.

Fibonacci

这里特意写成死循环, 让它不停地去消耗 CPU

2. 用 top 命令定位进程号

程序运行起来之后, 就该 top 命令出场了.

直接在命令行中输入

$top

top 命令的输出 use top 看到消耗 CPU 最高的就是一个 java 进程.

OK, 记下进程号 100162

补充:
> top 添加 -c 参数可以查看到命令的参数信息
> 这样可以看到 java 具体执行的类, 定位更准确

3. 用 top -H -p 命令定位到线程号

现在, 我们知道消耗 CPU 最高的进程是哪个了.

但我们还不知道具体是哪个线程的问题, 所以不着急用 jstack 去获取 java 进程快照.

再次使用 top 命令, 不过, 这次我们加上 -H -p 参数来查看线程运行情况.

$ top -H -p 100162

注: 也可以 top -p <pid> 后再敲 H 打开子线程信息

这次, 得到如下图的结果: use top -H -p (pid)

消耗 CPU 最高的不再是 100162 了. 可以清楚的看到是线程 100172

4. 用 jstack 定位到代码行

下面, 就可以用 jstack 来导出进程的堆栈信息了.

$jstack 100162
  • 这里不能直接使用 jstack 100172的形式, jstack 似乎只能对主线程使用
  • jstack 不能导出堆栈问题解决: jstack 不能导出堆栈

然后, 在堆栈信息中找到 nid=0x27bc(100172 的 16 进制) 的线程.

就是下面的 Thread-0 线程了

use jstack

全是 Fibonacci.calcFibo (testJstack.java:28)

定位源码文件 testJstack.java 第 28 行, 最土最慢最二的蜚波那契数列算法…

get the criminal

问题定位结束

上完整源码

  java
  java, jstack, top, 堆栈