[TOC]
使用 JVM Jsatck 命令定位使服务器 CPU 爆炸的类 & 方法。
首先给出一段示例代码:
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 堆栈信息

进入 top 使用 shift + h 查看占用 CPU 较高的线程号

可以看到占用 CPU 较高的线程号是 14226
使用打印出的 dump 信息查看线程信息。
使用 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









