Java进程CPU跑高分析
Java进程CPU飙升是最常见的线上问题,核心原因90%集中在:死循环、频繁GC、线程死锁/活锁、密集计算、大量阻塞等待。
我给你整理一套直接能用、零废话、生产环境标准流程,从定位到根因一次性讲透。
一、第一步:快速确认是哪个进程占用CPU高
命令(Linux)
top
找到 CPU% 最高的 Java 进程 PID。
二、第二步:定位是哪个线程在疯狂消耗CPU
# 查看该Java进程下所有线程的CPU占用
top -H -p <PID>
找到 CPU最高的线程 TID(十进制)。
把线程ID转成十六进制(jstack需要)
printf "%x\n" <TID>
得到一个十六进制字符串,例如 nid=0x1234。
三、第三步:导出线程栈,找到具体代码
jstack -l <PID> > stack.log
打开 stack.log,搜索刚才的十六进制 TID,就能直接定位到:
- 哪个类
- 哪个方法
- 哪一行代码
正在疯狂执行。
四、第四步:排查是不是GC导致的CPU高(非常常见)
如果发现很多GC线程占用CPU,说明不是业务代码死循环,而是内存泄漏/频繁GC。
检查GC情况
jstat -gc <PID> 1000 10
看这3个指标判断GC问题
- YGC 每秒多次 → 新生代太小/对象创建太快
- FGC 频繁 → 内存泄漏、老年代爆满
- GCT 时间占比高 → GC消耗大量CPU
导出堆内存分析
jmap -dump:format=b,file=heap.hprof <PID>
用 MAT/JProfiler/Arthas 打开,查看:
- 大对象
- 内存泄漏
- 集合未释放
五、最常见的4种CPU高根因
1. 死循环(最高发)
while(true){
// 无sleep、无阻塞
}
特征:单线程CPU 100%,栈一直停留在某行代码。
2. 频繁GC(第二高发)
特征:GC线程占用CPU高,FGC/YGC次数爆炸。
3. 大量线程阻塞/自旋等待
例如:
synchronized高竞争CAS无锁自旋- 线程池满了疯狂重试
4. 密集计算
加密、压缩、解析、循环计算,正常但压CPU。
六、最快工具:Arthas(推荐!一键定位CPU高)
如果你不想敲命令,直接用阿里开源的 Arthas,30秒定位问题:
# 安装
curl -O https://arthas.aliyun.com/arthas-boot.jar
java -jar arthas-boot.jar
一键查看CPU最高的线程
thread -n 3
直接显示:CPU最高的3个线程 + 代码行号。
一键查看GC
dashboard
七、完整排查流程总结
top找到Java进程PIDtop -H -p PID找到耗CPU的线程TID- 转十六进制
jstack导出栈 → 搜索定位代码jstat检查是否GC问题- Arthas 一键定位(最简单)
总结
- 单线程CPU 100% → 大概率死循环
- GC线程CPU高 → 内存泄漏/频繁GC
- 多线程CPU高 → 锁竞争、密集计算、大量任务