Java 应用 CPU 过高排查全流程

Java CPU 飙高90% 都是业务代码死循环、频繁GC、密集计算、死锁/自旋 导致的,排查有标准、固定、可落地的流程,不需要猜。

下面给你一套从登录服务器到定位代码行的完整实战步骤,直接照着做就能定位问题。


一、快速定位:哪个进程占用 CPU 最高

1. 查看系统整体 CPU 占用

bash 复制代码
top

找到 CPU 使用率最高的 Java 进程 PID(第一列)。


二、精准定位:这个进程里哪个线程在耗 CPU

2. 查看该 Java 进程内的线程排行

bash 复制代码
top -H -p <PID>

会列出该 Java 进程内部所有线程 ,找到CPU 最高的线程 TID

3. 把线程 TID 转成 16 进制(JVM 栈用 16 进制标识线程)

bash 复制代码
printf "%x\n" <TID>

得到一个16 进制线程 ID(记下来,后面要用)。


三、抓取线程栈:找到耗 CPU 的代码

4. 导出 Java 线程栈

bash 复制代码
jstack <PID> > stack.log

5. 在栈文件里搜索刚才的 16 进制线程 ID

bash 复制代码
grep -A 20 <16进制TID> stack.log

-A 20 表示显示后 20 行,直接就能看到:

  • 线程名称
  • 线程状态
  • 具体耗 CPU 的代码类、方法、行号

四、最常见的 4 种 CPU 飙高原因(一看栈就知道)

1. 死循环 / 无限递归(最常见)

栈特征:

复制代码
com.xxx.service.UserService.getUserList(UserService.java:88)

代码一直卡在同一行,没有阻塞,一直在跑。

2. 频繁 Full GC / Young GC

栈特征:

复制代码
VM Thread
GC task thread

排查命令:

bash 复制代码
jstat -gc <PID> 1000 10

如果 FGC(FullGC次数)每秒涨好几次,就是内存泄漏/GC 导致 CPU 高。

3. 大量锁自旋 / CAS 空循环

栈特征:

复制代码
sun.misc.Unsafe.park
java.util.concurrent.locks

线程处于 RUNNABLE 但一直在自旋

4. 密集计算(加密、循环、正则、JSON 解析)

栈会停留在:

  • 加密工具类
  • 复杂 for 循环
  • 正则表达式(灾难性回溯)
  • JSON/XML 序列化

五、1 分钟快速排查脚本(直接复制用)

把下面内容保存为 check_cpu.sh,一键定位耗 CPU 代码行:

bash 复制代码
#!/bin/bash
PID=$1
jstack $PID > stack.log
TID=$(top -b -n 1 -H -p $PID | grep java | sort -nrk 9 | head -1 | awk '{print $1}')
HEX_TID=$(printf "%x\n" $TID)
echo "高耗CPU线程16进制:$HEX_TID"
grep -A 30 $HEX_TID stack.log

使用:

bash 复制代码
chmod +x check_cpu.sh
./check_cpu.sh <Java进程PID>

六、定位到代码后怎么解决?

  1. 死循环:检查循环条件、边界值、迭代逻辑
  2. 频繁GC:查内存泄漏(用 jmap 堆 dump)、调整堆大小
  3. 锁自旋:改用公平锁、减少锁竞争、异步化
  4. 密集计算:异步执行、分片、缓存结果、优化算法

七、必备工具(无需安装)

Linux + JDK 自带,生产环境直接用

  • top:看进程/线程 CPU
  • jstack:线程栈
  • jstat:GC 监控
  • jmap:堆内存 dump(定位内存泄漏)

总结

  1. top 找 Java 进程 PID
  2. top -H 找耗 CPU 线程 TID
  3. 转 16 进制
  4. jstack + grep 定位代码行
  5. 按栈特征判断是死循环/GC/锁/密集计算

整个流程不重启、不影响业务、1~3 分钟定位根因

相关推荐
醉颜凉5 小时前
Java 必看:如何彻底避免 HashMap 多线程死循环问题?
java·开发语言
默 语5 小时前
Java新手入门:从零开始安装JDK并配置环境变量
java·开发语言·python·mysql·group by·1024程序员节·数据去重
何以解忧,唯有..5 小时前
高并发下超卖问题解决方案:从数据库到分布式锁的完整实践
java
Brilliantwxx6 小时前
【STM32】 I2C_EEPROM_test 工程(实战篇)
开发语言·stm32·单片机·嵌入式硬件·ecmascript
行者全栈架构师6 小时前
Spring Boot 接入 MaxKey 单点登录:6 个内部系统,一次登录全通行
java·vue.js·后端
清水白石0086 小时前
Python 异步编程深度解析:Cancellation 到底是异常还是控制信号?从 asyncio 取消机制到企业级事务设计最佳实践
开发语言·python
kolyle6 小时前
万级 QPS 下的 Token 分发系统架构:从 0 到 1 跑通 AI 时代的“水电煤“
开发语言·人工智能·系统架构·token·qps·极智词元·大模型私有化部署
木白CPP6 小时前
Linux DMA驱动详解(二)-----DMA的使用者
java·linux·运维
caoerzhong6 小时前
JeeWMS 开源仓库管理系统 GPL-3.0 合规指南:Java WMS 二次开发前必须弄清的授权边界
java·开发语言·开源·vue
Patrick在香港6 小时前
Python 审计香港开放数据目录:两个端点差 10 倍,只有 9.3% 的资源标了「最后修改时间」
开发语言·数据库·python·数据分析·api·数据治理·开放数据