# 协同Java进程CPU一直占用不释放

# 背景

查看协同的JDK进程,看到CPU一直保持在某个点位,不下降。

正常情况应该是:无人使用时CPU下降到个位数甚至为0,有人使用时才上升。

现象如下:协同的java一直保持在100%左右的CPU占用未释放:

1776406280441.png

提醒:在信创和 Linux 系统下 CPU 100% 不代表被占满,这里的 101.0% 实际是单核心的 CPU 使用率,说明该 Java 进程已经把其中一颗CPU物理核心跑满了,但CPU往往是多核心,其他核心仍处于空闲状态。

在信创或Linux下,通过top命令查看CPU运行情况之后,还需要按数字1键,就能看到全部CPU核心的运行情况。 其中如下图所示 0.0 id表示该CPU核心空闲为0,等于该核心被占满;而其它CPU核心都是 99.x id100 id 表示99%空闲 或 100%空闲。

1776407505617.png

# 分析方法

CPU占用持续但没打满,大概率不是死循环,而是:

  • 定时任务 / 后台线程一直在做计算(比如同步、报表、审批流)
  • 数据库查询慢导致线程一直在重试或等待
  • 死锁 / 锁竞争导致线程自旋

标准排查方法分三步:

  • 1、top 命令 → 找到占CPU高的 Java 进程 PID
  • 2、top -H -p PID 命令 → 找到这个进程里,哪个线程 占CPU最高
  • 3、jstack PID 命令 → 抓到这个线程在执行什么代码

第一步:top命令找到CPU占用高的Java进程PID,如下图所示为91795:

1776407703929.png

第二步:top -H -p 上一步获取的PID 找到这个进程里,哪个线程 占CPU最高,如下图所示名为 Log4j2-TF-95-As 的线程一直持有CPU占有:

1776407800887.png

第三步:到jdk的bin目录下运行 jstack 第一步获取的PID > javadump.txt导出当前Java的运行线程,然后找到上一步的Log4j2-TF-95-As具体堆栈,分析原因。

如下图所示,通过 cat javadump.txt | grep -A 20 'Log4j2-TF-95-As' 能看到 占用CPU的 Log4j2-TF-95-As 线程具体在干什么:

当前问题是因为启动参数中添加了-DAsyncLoggerConfig.WaitStrategy=YIELD,导致Log4j2 异步日志线程在没有日志写入时,不休眠而是反复调用 Thread.yield() 空转,导致日志线程占用CPU资源,修改bin\catalina_custom.bat文件将-DAsyncLoggerConfig.WaitStrategy值改为SLEEP,然后重启OA服务。 关联支持单:JSFW-2026-01843

1776408997955.png

最后的最后,如果你找到了线程,还不知道它为什么占用,你可以:

  • 将问题线程截图发给AI分析
  • 将javadump.txt和你发现的问题上报BUG给研发分析
编撰人:het