java项目中cpu飙升排查及解决方法

下面给你一套 生产环境可直接照抄执行的「Java CPU 飙升排查 & 解决全指南」

不堆概念,全是实战步骤 ,适合你现在这种 多 Java 服务混布、CPU 突然飙高​ 的场景。


一、CPU 飙升的本质(先搞清方向)

Java 中 CPU 高 ≠ 一定是死循环

常见原因只有这几类:

类型 占比
GC 频繁(最常见) 40%
死循环 / 计算密集 25%
线程阻塞 + 自旋 15%
锁竞争(synchronized / CAS) 10%
外部调用阻塞(Redis / DB / 下游) 10%

👉 先定位是哪一类,再谈解决


二、CPU 飙升排查标准流程(5 步)

✅ Step 1:找到"谁在吃 CPU"

复制代码
top

记下 Java 进程 PID(比如 29968)

再看线程级:

复制代码
top -Hp <PID>

你会看到:

  • 某个线程 PID(TID)CPU 特别高(如 80%、90%)

✅ Step 2:把 TID 转成 16 进制(非常关键

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

得到类似:

复制代码
0x3f2a

✅ Step 3:看这个线程在干什么(90% 能定位)

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

然后搜索:

复制代码
nid=0x3f2a

你会看到类似:

✅ 情况 1:GC 线程(最常见)

复制代码
"GC task thread#0" os_prio=0 tid=... nid=0x3f2a runnable

👉 不是业务代码问题,是内存问题


✅ 情况 2:业务线程死循环

复制代码
"http-nio-8080-exec-12" nid=0x3f2a runnable
   at com.xxx.service.DeviceCache.lambda$update$1(DeviceCache.java:78)

👉 直接定位到代码行


✅ 情况 3:锁竞争

复制代码
BLOCKED (on object monitor)
waiting for monitor entry

👉 锁粒度太大 / synchronized 滥用


✅ 情况 4:线程池堆积

复制代码
WAITING (parking)
java.util.concurrent.LinkedBlockingQueue.take

👉 任务处理不过来


✅ Step 4:确认是不是 GC 导致的 CPU 高(必做)

复制代码
jstat -gc <PID> 1000 5

重点看:

指标 危险信号
FGC 频繁 Full GC
FGCT Full GC 时间很长
OU Old 区几乎满了

✅ 如果 GC 频繁 + CPU 高

👉 CPU 高是结果,内存泄漏是原因


✅ Step 5:看有没有"异常线程数"

复制代码
jstack <PID> | grep java.lang.Thread | wc -l
线程数 说明
< 300 正常
500~1000 偏高
> 1500 高危

三、不同原因的解决方案(对症下药)

🔴 1️⃣ GC 导致 CPU 飙高(最常见)

✅ 解决步骤

1️⃣ 立刻加 JVM 参数:

复制代码
-Xms2g
-Xmx2g
-XX:+UseG1GC
-XX:MaxGCPauseMillis=200
-XX:MaxDirectMemorySize=512m

2️⃣ 抓堆:

复制代码
jmap -dump:live,format=b,file=cpu_gc.hprof <PID>

3️⃣ 查:

  • 静态 Map

  • 本地缓存

  • 大对象数组


🔴 2️⃣ 死循环 / 计算密集

✅ 典型代码

复制代码
while(true) {
    doSomething();
}

✅ 解决

  • 加 sleep

  • 加退出条件

  • 改成定时任务(ScheduledExecutor)


🔴 3️⃣ 锁竞争导致 CPU 高

✅ 错误示例

复制代码
synchronized(this) { ... }

✅ 优化

  • 缩小锁范围

  • 使用 ReentrantLock

  • 用并发容器(ConcurrentHashMap


🔴 4️⃣ 线程池失控

✅ 错误示例

复制代码
Executors.newCachedThreadPool();

✅ 正确做法

复制代码
new ThreadPoolExecutor(
    10,
    50,
    60,
    TimeUnit.SECONDS,
    new LinkedBlockingQueue<>(1000),
    new ThreadPoolExecutor.CallerRunsPolicy()
);

🔴 5️⃣ Redis / DB 慢导致 CPU 高

✅ 排查

  • Redis slowlog

  • MySQL slow query log

  • 连接池耗尽

✅ 解决

  • 加缓存

  • 限流

  • 异步化


四、线上应急处理清单(可直接用)

场景 操作
CPU > 80% top → 找 PID
单核 CPU 100% top -Hp → jstack
GC 导致 扩内存 / 重启
死循环 紧急回滚
线程爆炸 限流 / 降级

五、你当前环境的高危提示(结合前面)

结合你之前的 ps

服务 风险
vehicleGPSServer ⚠️ 高 CPU + 小堆(极易 GC 飙 CPU)
deviceService ⚠️ 无 -Xmx(GC 风险)
platformService ⚠️ 平台级缓存风险

你现在遇到的 CPU 高,90% 是 GC 引起


六、一句话总结(记住这句)

Java CPU 飙升,90% 不是 CPU 的问题,而是内存 + 线程的问题。


如果你愿意,我可以帮你:

1️⃣ 对着你某个高 CPU PID 一步步在线定位

2️⃣ **解读 jstack / jstat 输出(你贴出来就行)**​

3️⃣ 给你一份《Java 服务 CPU 飙高应急手册》

你只需要说:

相关推荐
nanxun88621 小时前
记一次诡异的 Docker 容器"串包"故障排查
java
用户1563068103511 天前
Day01 | Java 基础(Java SE)
java
行者全栈架构师1 天前
Maven dependency:tree 的 8 个高级用法
java·后端
行者全栈架构师1 天前
IDEA 中 Maven 项目的 15 个红色报错快速解决方法
java·后端
令人头秃的代码0_01 天前
mac(m5)平台编译openjdk
java
唐青枫2 天前
Java JDBC 实战指南:从 Connection 到事务和连接池
java
一个做软件开发的牛马2 天前
MyBatis-Plus 从零实战:完整搭建可运行 Demo,BaseMapper 零 SQL、Wrapper 条件构造、分页插件与代码生成器详解
java·后端
用户3721574261352 天前
Java 处理 PDF 图片:提取 PDF 中的图片,并压缩 PDF 图片体积
java
用户3721574261352 天前
Java 打印 Word 文档:从基础打印到高级设置
java
用户3521802454753 天前
当 Prompt 学会"热更新":Spring Boot × Nacos3 AI 实战
java·spring boot·ai编程