如何快速定位JVM中消耗CPU最多的线程?

在日常 Java 的开发中,性能调优肯定是很多人不能绕开的一个环节。而其中最简单,也是最基础的一个问题就是如何定位消耗 CPU 最多的线程。这篇文章中你假笨以一个简单的 Test 例子为蓝本,给各位总结了分析这类问题的常用『套路』。
具体如下:
如何快速定位JVM中消耗CPU最多的线程?

这个例子里新创建了 11 个线程,其中 10 个线程没干什么事,主要是 sleep,另外有一个线程在循环里一直跑着,可以想象这个线程是这个进程里最耗 CPU 的线程了,那怎么把这个线程给抓出来呢?

首先我们可以通过top -Hp 来看这个进程里所有线程的 CPU 消耗情况,得到类似下面的数据。

如何快速定位JVM中消耗CPU最多的线程?

拿到这个结果之后,我们可以看到 cpu 最高的线程是 pid 为 18250 的线程,占了 99.8%:
如何快速定位JVM中消耗CPU最多的线程?

接着我们可以通过 jstack的输出来看各个线程栈:
如何快速定位JVM中消耗CPU最多的线程?

上面的线程栈我们注意到 nid 的值其实就是线程 ID,它是十六进制的,我们将消耗 CPU 最高的线程18250,转成十六进制0X47A,然后从上面的线程栈里找到nid=0X47A的线程,其栈为:

“Busiest Thread” #28 prio=5 os_prio=0 tid=0x00007fb91498d000 nid=0x474a runnable [0x00007fb9065fe000] java.lang.Thread.State: RUNNABLE at Test$2.run(Test.java:18)

本文转载『你假笨』的微信公众号,你假笨(寒泉子)目前是 PerfMa 创始人之一兼 CEO,之前在阿里工作 7 年多,从事 JVM 相关工作,为各业务系统做性能优化,性能问题分析,是阿里性能分析平台的作者。