Java CPU 飙高90% 都是业务代码死循环、频繁GC、密集计算、死锁/自旋导致的,排查有标准、固定、可落地的流程,不需要猜。
下面给你一套从登录服务器到定位代码行的完整实战步骤,直接照着做就能定位问题。
一、快速定位:哪个进程占用 CPU 最高
1. 查看系统整体 CPU 占用
top找到CPU 使用率最高的 Java 进程 PID(第一列)。
二、精准定位:这个进程里哪个线程在耗 CPU
2. 查看该 Java 进程内的线程排行
top-H-p<PID>会列出该 Java 进程内部所有线程,找到CPU 最高的线程 TID。
3. 把线程 TID 转成 16 进制(JVM 栈用 16 进制标识线程)
printf"%x\n"<TID>得到一个16 进制线程 ID(记下来,后面要用)。
三、抓取线程栈:找到耗 CPU 的代码
4. 导出 Java 线程栈
jstack<PID>>stack.log5. 在栈文件里搜索刚才的 16 进制线程 ID
grep-A20<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排查命令:
jstat-gc<PID>100010如果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 代码行:
#!/bin/bashPID=$1jstack$PID>stack.logTID=$(top-b-n1-H-p$PID|grepjava|sort-nrk9|head-1|awk'{print $1}')HEX_TID=$(printf"%x\n"$TID)echo"高耗CPU线程16进制:$HEX_TID"grep-A30$HEX_TIDstack.log使用:
chmod+x check_cpu.sh ./check_cpu.sh<Java进程PID>六、定位到代码后怎么解决?
- 死循环:检查循环条件、边界值、迭代逻辑
- 频繁GC:查内存泄漏(用 jmap 堆 dump)、调整堆大小
- 锁自旋:改用公平锁、减少锁竞争、异步化
- 密集计算:异步执行、分片、缓存结果、优化算法
七、必备工具(无需安装)
Linux + JDK 自带,生产环境直接用:
top:看进程/线程 CPUjstack:线程栈jstat:GC 监控jmap:堆内存 dump(定位内存泄漏)
总结
- top找 Java 进程 PID
- top -H找耗 CPU 线程 TID
- 转 16 进制
- jstack + grep定位代码行
- 按栈特征判断是死循环/GC/锁/密集计算
整个流程不重启、不影响业务、1~3 分钟定位根因。