HOOOS

手把手教你:如何从jstack日志中揪出死锁线程

0 3 Debug侠 jstack死锁线程分析
Apple

线上环境突然卡死,没有可视化工具,只能拿到 jstack 日志,面对几万行的文本,确实让人头大。别慌,这里提供一套系统性的方法,帮你从 jstack 日志中揪出死锁线程。

第一步:拿到 jstack 日志

这个不用多说,使用 jstack pid > jstack.log 命令拿到日志文件。

第二步:初步筛选,关注关键信息

用文本编辑器打开 jstack.log 文件,直接搜索以下关键字,快速定位问题:

  • deadlock:这是最直接的死锁提示,jstack 会自动检测死锁并打印相关信息。
  • waiting to lock:线程等待锁的标志,关注哪些线程在等待锁。
  • 持有锁的线程 (owned by):找到持有锁的线程,看看它在做什么。
  • BLOCKED:线程阻塞状态,长时间处于阻塞状态的线程可能存在问题。

第三步:分析死锁信息(如果找到 deadlock 关键字)

如果 jstack 输出了死锁信息,通常会包含以下内容:

  • Found one Java-level deadlock: 表示发现了一个 Java 级别的死锁。
  • 线程信息: 哪些线程参与了死锁,以及它们正在等待的锁。
  • 锁信息: 哪个线程持有了哪些锁,导致其他线程无法继续执行。

仔细阅读这些信息,就能直接定位到死锁的线程和锁。例如:

Found one Java-level deadlock:
=============================
"thread-1":
  waiting to lock monitor 0x00007f... (a java.lang.Object)
  which is held by "thread-2"
"thread-2":
  waiting to lock monitor 0x00007f... (a java.lang.Object)
  which is held by "thread-1"

这个例子中,thread-1thread-2 互相等待对方持有的锁,导致死锁。

第四步:如果没有死锁信息,手动分析线程状态

如果 jstack 没有直接提示死锁,就需要手动分析线程状态。

  1. 查找 BLOCKED 状态的线程: 筛选出所有状态为 BLOCKED 的线程。
  2. 分析线程堆栈: 查看这些线程的堆栈信息,找到它们正在等待的锁。
  3. 找到持有锁的线程: 根据锁的信息,找到持有这些锁的线程。
  4. 分析锁的竞争情况: 如果多个线程都在竞争同一个锁,并且其中一个线程长时间持有该锁,就可能导致死锁或性能问题。

第五步:重点关注业务线程

在分析 jstack 日志时,要重点关注业务线程,通常线程名会包含业务相关的关键字,例如订单、支付、用户等。 忽略 JVM 自身线程 (如 GC 线程)。

第六步:借助工具提高效率

虽然没有可视化工具,但可以使用一些文本处理工具来提高效率,例如:

  • grep: 用于快速搜索关键字。
  • awk/sed: 用于提取和格式化文本。
  • 文本编辑器: 使用文本编辑器的查找、替换、高亮等功能,方便分析日志。

总结:

分析 jstack 日志需要耐心和细心, 掌握以上方法,就能快速定位死锁线程,解决线上问题。记住,关键在于理解线程状态、锁的竞争情况,以及业务代码的逻辑。

点评评价

captcha
健康