0

0

如何使用jstack工具排查死锁_控制台输出日志的定位与分析技巧

P粉602998670

P粉602998670

发布时间:2026-02-19 10:19:32

|

617人浏览过

|

来源于php中文网

原创

jstack仅能检测java层synchronized和lock的循环等待死锁,对jni、文件锁等无效;死锁信息固定位于输出末尾,需比对waiting to lock与locked的监视器地址是否交叉;建议用jstack -l重定向后grep筛查。

如何使用jstack工具排查死锁_控制台输出日志的定位与分析技巧

死锁没打印堆栈?先确认 jstack 是否真能捕获到

很多情况下你执行了 jstack <pid></pid>,但输出里压根没有 “Found 1 deadlock” 提示,不是工具失效,而是 JVM 没检测到符合标准的循环等待——它只识别由 java.util.concurrent.locks.Lock 和内置 synchronized 构成的、且线程状态为 BLOCKEDWAITING 的闭环。如果死锁涉及 JNI、文件锁、数据库连接或自定义非阻塞同步逻辑,jstack 就完全看不到。

  • 运行前加 -XX:+UseParallelGC 或其它非默认 GC 不影响死锁检测,但 -XX:+UnlockDiagnosticVMOptions -XX:+LogVMOutput 这类诊断开关也帮不上忙
  • 必须确保目标进程是正在运行的 Java 进程(ps aux | grep java 看 PID),不是已挂起或僵死的 zombie 进程
  • 如果用 jstack -l <pid></pid>,会额外显示 java.util.concurrent 锁的持有者和等待者,比默认输出更准,建议养成加 -l 的习惯

jstack 输出里怎么快速定位死锁线索

别从头扫日志。死锁信息永远在最底部,且只有两段固定格式:一段是 “Found 1 deadlock.”,紧接着是每个死锁线程的完整堆栈快照,中间用空行隔开。关键不是看“在哪个方法卡住”,而是比对“谁持有什么锁”和“在等什么锁”。

  • 找关键词:waiting to lock 表示该线程想获取某个对象监视器;locked 表示它当前正持有这个锁
  • 两个线程的 waiting to locklocked 地址如果交叉出现(比如 A 等 B 持有的锁,B 又等 A 持有的锁),就是典型死锁
  • 注意地址值是否一致: 是对象监视器 ID,不是内存地址,同一 JVM 内重复出现即代表同一把锁

控制台日志太刷屏?用重定向 + grep 快速过滤

直接敲 jstack <pid></pid> 在终端里跑,容易被其他日志冲掉关键段,而且没法回溯。必须把输出落地再处理。

AI抖音
AI抖音

AI抖音,会思考的抖音

下载
  • 推荐命令:jstack -l <pid> > jstack.out 2>&1</pid>,这样连可能的错误(如权限拒绝)也一并捕获
  • 快速筛查:用 grep -A 20 "Found 1 deadlock" jstack.out 直接拿到死锁上下文;若没结果,再试 grep -E "waiting to lock|locked" jstack.out | head -20 看是否有可疑锁竞争
  • 别用 tail -f 实时盯 jstack 输出——它是一次性快照,不是流式日志,实时盯没意义

为什么本地复现不了,线上却频繁死锁?

根本原因不是代码不同,而是线程调度时机和锁获取顺序的概率差异。本地单核或低并发下,两个线程几乎不会“恰好”以相反顺序抢两把锁;而线上多核+高并发,这种竞态窗口被极大放大。

  • 检查是否用了静态工具类里的双重检查单例(Double-Checked Locking),尤其在 getInstance() 中混用 synchronizedvolatile 不当时极易触发
  • 留意日志中反复出现的线程名(如 pool-2-thread-3),它们可能长期复用,导致锁状态累积;而本地每次都是新线程,状态干净
  • 如果用了 CompletableFuture 链式调用 + 自定义线程池,要特别注意 thenApplythenAccept 是否跨线程访问了共享可变对象——jstack 看不到这种逻辑死锁,只能靠代码审计

真正难的从来不是看到死锁,而是判断哪一行代码让两个线程走上了互等的路径。堆栈只是终点,起点藏在锁的申请顺序里。

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
c++怎么把double转成int
c++怎么把double转成int

本专题整合了 c++ double相关教程,阅读专题下面的文章了解更多详细内容。

254

2025.08.29

C++中int、float和double的区别
C++中int、float和double的区别

本专题整合了c++中int和double的区别,阅读专题下面的文章了解更多详细内容。

105

2025.10.23

c++中volatile关键字的作用
c++中volatile关键字的作用

本专题整合了c++中volatile关键字的相关内容,阅读专题下面的文章了解更多详细内容。

71

2025.10.23

堆和栈的区别
堆和栈的区别

堆和栈的区别:1、内存分配方式不同;2、大小不同;3、数据访问方式不同;4、数据的生命周期。本专题为大家提供堆和栈的区别的相关的文章、下载、课程内容,供大家免费下载体验。

419

2023.07.18

堆和栈区别
堆和栈区别

堆(Heap)和栈(Stack)是计算机中两种常见的内存分配机制。它们在内存管理的方式、分配方式以及使用场景上有很大的区别。本文将详细介绍堆和栈的特点、区别以及各自的使用场景。php中文网给大家带来了相关的教程以及文章欢迎大家前来学习阅读。

594

2023.08.10

堆和栈的区别
堆和栈的区别

堆和栈的区别:1、内存分配方式不同;2、大小不同;3、数据访问方式不同;4、数据的生命周期。本专题为大家提供堆和栈的区别的相关的文章、下载、课程内容,供大家免费下载体验。

419

2023.07.18

堆和栈区别
堆和栈区别

堆(Heap)和栈(Stack)是计算机中两种常见的内存分配机制。它们在内存管理的方式、分配方式以及使用场景上有很大的区别。本文将详细介绍堆和栈的特点、区别以及各自的使用场景。php中文网给大家带来了相关的教程以及文章欢迎大家前来学习阅读。

594

2023.08.10

线程和进程的区别
线程和进程的区别

线程和进程的区别:线程是进程的一部分,用于实现并发和并行操作,而线程共享进程的资源,通信更方便快捷,切换开销较小。本专题为大家提供线程和进程区别相关的各种文章、以及下载和课程。

675

2023.08.10

pixiv网页版官网登录与阅读指南_pixiv官网直达入口与在线访问方法
pixiv网页版官网登录与阅读指南_pixiv官网直达入口与在线访问方法

本专题系统整理pixiv网页版官网入口及登录访问方式,涵盖官网登录页面直达路径、在线阅读入口及快速进入方法说明,帮助用户高效找到pixiv官方网站,实现便捷、安全的网页端浏览与账号登录体验。

561

2026.02.13

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
WEB前端教程【HTML5+CSS3+JS】
WEB前端教程【HTML5+CSS3+JS】

共101课时 | 9.4万人学习

JS进阶与BootStrap学习
JS进阶与BootStrap学习

共39课时 | 3.3万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号