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

下面给你一套从登录服务器到定位代码行的完整实战步骤,直接照着做就能定位问题。
top
找到 CPU 使用率最高的 Java 进程 PID(第一列)。
top -H -p <PID>
会列出该 Java 进程内部所有线程,找到CPU 最高的线程 TID。
printf "%xn" <TID>
得到一个16 进制线程 ID(记下来,后面要用)。
jstack <PID> > stack.log
grep -A 20 <16进制TID> stack.log
-A 20 表示显示后 20 行,直接就能看到:
栈特征:
com.xxx.service.UserService.getUserList(UserService.java:88)
代码一直卡在同一行,没有阻塞,一直在跑。
栈特征:
VM Thread GC task thread
排查命令:
jstat -gc <PID> 1000 10
如果 FGC(FullGC次数)每秒涨好几次,就是内存泄漏/GC 导致 CPU 高。
栈特征:
sun.misc.Unsafe.park java.util.concurrent.locks
线程处于 RUNNABLE 但一直在自旋。
栈会停留在:
把下面内容保存为 check_cpu.sh,一键定位耗 CPU 代码行:
#!/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 "%xn" $TID)
echo "高耗CPU线程16进制:$HEX_TID"
grep -A 30 $HEX_TID stack.log
使用:
chmod +x check_cpu.sh ./check_cpu.sh <Java进程PID>
Linux + JDK 自带,生产环境直接用:
top:看进程/线程 CPUjstack:线程栈jstat:GC 监控jmap:堆内存 dump(定位内存泄漏)整个流程不重启、不影响业务、1~3 分钟定位根因。