[TOC]
使用 JVM Jsatck 命令定位使服务器 CPU 爆炸的类 & 方法。
CentOS 7 服务下
首先给出一段示例代码:
import java.util.Random;
import java.util.UUID;
import java.util.concurrent.atomic.AtomicInteger;
/**
* Hello world!
*/
public class App {
private static final AtomicInteger atomic = new AtomicInteger(0);
private static final Integer randomInteger = new Random().nextInt(100);
private static final Object LOCK = new Object();
public static void main(String[] args) {
for (int i = 0; i < 100; i++) {
synchronized (LOCK) {
threadFunc();
atomic.addAndGet(1);
}
}
}
public static void threadFunc() {
new Thread(() -> {
if (randomInteger.equals(atomic.get())) {
// 这里会让服务器出现 CPU 100% 占用
while (!UUID.randomUUID().toString().equals("HELLO,WORLD!")) {
}
}
}).start();
}
}
使用 top 命令查看服务器资源占用情况
可以很明显的看到 PID 为 14168 的 java 程序出现了 CPU 99.9 % 的占用
使用 Jvm jps 命令确认占用CPU过高的程序
可以看到 14168 是名称为 APP 的程序。
使用 Jvm jstack 命令打印出 dump 堆栈信息
jstack [pid] > ps.log
进入 top 使用 shift + h 查看占用 CPU 较高的线程号
可以看到占用 CPU 较高的线程号是 14226
使用打印出的 dump 信息查看线程信息。
首先将 14226 转换为 16 进制。
printf '%x\n' 14226
输出3792
使用 grep -A 20 3792 ps.log
查看线程信息
可以看到是 App.java 文件 中的 threadFunc 方法。
总结
- Top 命令查看CPU过高的应用
- 使用 Jps 命令定位程序
- 使用 jstack [pid] > [文件] 打印出 dump 文件
- 进入 top 使用 shift + h 切换查看线程信息
- 使用 printf '%x\n' [tid] 将线程ID转换为 16 进制
- 进入 dump 文件通过转换过后的 16 进制线程号。搜索线程信息。定位类和方法。
- 人工分析代码BUG