一、jstack 工具说明

1. 工具作用

jstack 是 JDK 自带的JVM 线程堆栈分析工具,用于导出当前 Java 进程内所有线程的运行状态、调用栈、锁信息、线程状态,是定位 Java 性能问题的核心工具。

2. 主要使用场景

  • Java 进程 CPU 占用过高(100%、800%+)
  • 线程死锁、循环等待
  • 服务夯死、接口不响应
  • 线程过多、线程泄漏
  • 代码死循环、高频计算

3. 常用标准命令

# 查看线程堆栈(基础)
jstack <PID>

# 显示额外锁信息(推荐生产使用)
jstack -l <PID>

# 进程僵死无响应时强制导出
jstack -F <PID>

# 导出堆栈到日志文件(排查必用)
jstack -l <PID> > jstack_$(date +%Y%m%d%H%M).log

二、Java 进程 CPU 过高 标准排查流程

步骤 1:找到 CPU 占用最高的 Java 进程 PID

top
  • 查看 % CPU 列,找到占用最高的 Java 进程
  • 记录 PID(例如:1688)

步骤 2:定位该进程内最耗 CPU 的线程 TID

top -H -p <PID>
# 示例:top -H -p 1688
  • 显示该进程下所有线程
  • 找到 % CPU 最高的线程,记录十进制 TID(例如:1702)

步骤 3:将线程 TID 转换为十六进制

jstack 中的线程 ID(nid)是十六进制,必须转换:

printf "%x\n" <线程TID>
# 示例:printf "%x\n" 1702 → 输出 6a6
  • 得到 nid:0x6a6

步骤 4:使用 jstack 导出完整线程栈

jstack -l 1688 > stack_1688.log

步骤 5:在堆栈日志中搜索对应线程

grep -i 'nid=0x6a6' stack_1688.log -A 30
  • -A 30 显示后 30 行,展示完整调用链
  • 直接定位到高 CPU 线程的堆栈

步骤 6:分析堆栈定位问题代码

重点关注:

  • java.lang.Thread.State: RUNNABLE(高 CPU 几乎都是此状态)
  • 堆栈最下层的业务类、方法、行号,即为高 CPU 根源代码

三、线程堆栈关键字段解释

"Thread-1" prio=5 os_prio=0 tid=0x00007f... nid=0x6a6 runnable
java.lang.Thread.State: RUNNABLE
    com.example.biz.UserServiceImpl.getUserList(UserServiceImpl.java:95) ← 问题代码行
  • nid=0xXXX:操作系统线程 ID(十六进制)
  • runnable:线程正在运行(高 CPU 核心状态)
  • 堆栈自下而上:调用源头 → 上层逻辑

四、Java CPU 过高常见根本原因

  1. while(true) 死循环(最常见)
  2. 递归无退出条件
  3. 高频序列化 / 反序列化、JSON 解析
  4. 正则表达式极端回溯(ReDoS)
  5. 大量循环计算、复杂逻辑
  6. GC 异常(可配合 jstat 进一步确认)

五、极简记忆口诀(方便背诵)

  1. top 找进程 PID
  2. top -H 找线程 TID
  3. printf 转十六进制
  4. jstack 导出线程栈
  5. grep 搜 nid 定位代码
  6. 看栈底行解决问题
Logo

汇聚全球AI编程工具,助力开发者即刻编程。

更多推荐