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 飙高应急手册》

你只需要说:

相关推荐
IT枫斗者枫哥9 分钟前
子线程断言失败,JUnit 为什么还显示通过?
java·后端
码农小河661 小时前
基于PHP的电商后台蜜罐系统
开发语言·php
starzy19902 小时前
深入理解Scala柯里化函数:函数链式变换
开发语言·scala
ShineWinsu2 小时前
对于Qt:QTreeWidget常见属性以及QTreeWidgetItem类的解析
开发语言·c++·qt·gui·客户端·多叉树·qtreewidget
落羽的落羽2 小时前
【C++】C++17的主要特性
linux·服务器·开发语言·c++·算法·机器学习
考虑考虑2 小时前
JDK27中的Set.ofLazy
java·后端·java ee
文丑颜不良啊3 小时前
LeetCode2841~2860题目解析
java·leetcode
小南家的青蛙3 小时前
Tomcat与Jetty深度对比
java·tomcat·jetty
总要学点什么3 小时前
第108篇:三维特效-图片轨迹线效果——把贴图滚成一串箭头,想用它的本色反而整条消失
开发语言·javascript·ecmascript·gis·webgl·材质·cesium
乌暮4 小时前
Spring AOP 与 Spring 事务:用大白话彻底理解原理与实践
java·数据库·spring boot·后端·sql·学习·spring