Java 应用 CPU 使用率过高排查指南

1. 定位高 CPU 进程

使用 top 命令查看系统资源占用:

top -c  # 显示完整命令

  • Shift+P 按 CPU 排序
  • 记录目标 Java 进程的 PID(如 java -jar app.jar
2. 定位高 CPU 线程
top -Hp <PID>  # 查看该进程所有线程

  • Shift+P 排序,记录高 CPU 线程的十进制 ID(记为 $T_{dec}$)
3. 线程 ID 转换

将十进制线程 ID 转为十六进制:

Long.toHexString($T_{dec}$)  // Java 代码示例

或使用计算器: $$ T_{hex} = \text{Hex}(T_{dec}) $$

4. 分析线程堆栈

使用 jstack 获取线程快照:

jstack <PID> > thread_dump.log

在日志中搜索 $T_{hex}$,定位线程堆栈信息。

5. 使用 Arthas 动态诊断
安装并启动 Arthas:
curl -O https://arthas.aliyun.com/arthas-boot.jar
java -jar arthas-boot.jar <PID>

关键 Arthas 命令:
dashboard   # 实时监控所有线程 CPU 占用
thread -n 3 # 显示 CPU 占用最高的 3 个线程
thread <ID> # 查看指定线程堆栈(支持十进制 ID)
trace <ClassName> <MethodName> # 追踪方法耗时

6. 死循环定位示例

若发现类似堆栈:

"High-CPU-Thread" #17 prio=5 os_prio=0 cpu=5023ms elapsed=215.32s
    at com.example.LoopService.run(LoopService.java:12)

对应代码可能为:

while (true) {  // 死循环代码
    // 未设退出条件的循环
}

7. 解决方案
  • 立即处理:通过 Arthas 的 ognl 命令动态修改循环控制变量
  • 长期修复
    1. 添加循环终止条件
    2. 引入 Thread.sleep() 降低 CPU 空转
    3. 使用线程池管理任务
排查流程图
graph TD
    A[top 发现高 CPU 进程] --> B[top -Hp 定位线程]
    B --> C[ID 十进制转十六进制]
    C --> D[jstack 分析堆栈]
    D --> E{定位可疑代码}
    E -->|是| F[Arthas 动态验证]
    E -->|否| G[Arthas 线程分析]
    F/G --> H[修复代码]

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐