Java 死锁的4种排查工具

叶初
叶初
发布时间:2026-10-15| 4人浏览过
原创

本文介绍Java程序中死锁现象的形成条件,并详细演示如何通过jstack命令行、jconsole图形界面、jvisualvm综合监控工具以及jmc高级管理套件这四种官方工具快速定位和诊断死锁问题,帮助开发者高效解决线程阻塞故障。

死锁示例与成因

在Java开发中,死锁是指两个或两个以上的运算单元(进程、线程)都在等待对方停止执行,以取得系统资源,但没有一方提前退出,导致程序永久挂起。以下是一个经典的Java死锁案例:创建两个锁对象和两个线程,线程1先持有锁A等待锁B,而线程2先持有锁B等待锁A,从而形成相互等待。

public class DeadLockExample {
    public static void main(String[] args) {
        Object lockA = new Object(); // 创建锁 A
        Object lockB = new Object(); // 创建锁 B

        // 创建线程 1
        Thread t1 = new Thread(new Runnable() {
            @Override
            public void run() {
                synchronized (lockA) {
                    System.out.println("线程 1:获取到锁 A!");
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println("线程 1:等待获取 B...");
                    synchronized (lockB) {
                        System.out.println("线程 1:获取到锁 B!");
                    }
                }
            }
        });
        t1.start(); 

        // 创建线程 2
        Thread t2 = new Thread(new Runnable() {
            @Override
            public void run() {
                synchronized (lockB) {
                    System.out.println("线程 2:获取到锁 B!");
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println("线程 2:等待获取 A...");
                    synchronized (lockA) {
                        System.out.println("线程 2:获取到锁 A!");
                    }
                }
            }
        });
        t2.start(); 
    }
}

运行上述代码后,可以看到线程 1 和线程 2 都在等待对方释放锁,程序陷入停滞:

要避免或理解死锁,需了解产生死锁必须同时满足的四个条件:

  • 互斥条件:资源只能被一个运算单元占用。
  • 请求和保持条件:已持有资源的单元在等待新资源时不释放原有资源。
  • 不可剥夺条件:已获得的资源在未用完前不能被强制剥夺。
  • 环路等待条件:存在一条线程-资源的环形链,大家都在等下一个人的资源。

死锁排查方案

当程序出现异常停顿时,可以通过以下四种方式中的任一种进行分析排查。

第1步:使用 jstack 排查

目的:通过命令行快速获取当前 Java 虚拟机的线程堆栈快照。

  1. 获取 PID:打开终端或命令提示符,输入 jps -l 查看本机所有 Java 进程的 ID 和完整路径名。

找到对应的进程 ID(PID)后,执行 jstack -l <PID> 来发现死锁信息。

其中参数 -l 表示打印长列表,会包含关于锁的附加信息。如需查看更多使用说明,可运行 jstack -help。

第2步:使用 jconsole 排查

目的:通过图形化界面监控 Java 应用程序的资源消耗与线程状态。

  1. 启动工具:进入 JDK 安装目录下的 bin 文件夹,双击运行 jconsole.exe。
  1. 连接进程:在弹出的窗口中选择目标进程,勾选“不安全的连接”以跳过身份验证,然后点击“连接”。

若遇到安全警告弹窗,点击确认进入监控主页:

  1. 检测死锁:切换到顶部的“线程”选项卡,点击下方的“检测死锁”按钮。

稍等片刻,工具就会检测出当前的死锁详细信息及涉及的线程列表:

第3步:使用 jvisualvm 排查

目的:利用可视化综合工具进行深度故障排查,适合查看详细的线程 Dump。

  1. 启动工具:同样在 JDK 的 bin 目录下双击启动 jvisualvm。

加载完成后,左侧面板会自动列出本地运行的 Java 程序:

双击选中需要调试的应用程序:

  1. 分析线程:点击顶部菜单的“线程”标签页。

此时页面通常会直接显示是否存在死锁标识。为了保存现场或进一步研究,点击右侧的“线程 Dump”按钮即可生成详情报告:

第4步:使用 jmc 排查

目的:借助 Oracle Java Mission Control (jmc) 套件进行专业的 Java 性能管理与故障排除。

  1. 启动工具:从 JDK bin 目录启动 jmc。

查看主界面的应用列表:

  1. 开启监控:在左侧选中目标应用,右键选择“启动 JMX 控制台”。在展开的节点中点击“线程”,勾选“死锁检测”即可实时捕获死锁状态。

总结

死锁是典型的并发编程陷阱。在日常开发中,推荐根据场景选择合适的排查手段:对于简单的命令行环境可以使用 jstack;如果需要图形化展示和持续监控,推荐使用 JConsole 或功能更全面的 jvisualvm;而在需要进行深入底层剖析时,jmc 则是极佳的选择。

以上就是分享Java死锁的4种排查工具的详细内容,更多关于Java死锁排查的资料请关注本站其它相关文章!

相关标签:

免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。

Python 相关产品和应用

全部下载
Selenium

Selenium

4.51.0 · Windows

用于浏览器自动化和 Web 测试的 Python 工具。

scikit-learn

scikit-learn

1.9.1 · Windows

常用 Python 机器学习算法与模型评估工具库。

Black

Black

26.10.1 · Windows

强调一致性的 Python 自动代码格式化工具。

Ruff

Ruff

0.17.1 · macOS

由 Rust 编写的高速 Python 代码检查和格式化工具。

pytest

pytest

9.1.1 · Windows

简洁而强大的 Python 自动化测试框架。

FastAPI

FastAPI

0.146.0 · Windows

高性能 Python API 框架,支持类型提示和自动接口文档。

Flask

Flask

3.1.3 · Windows

轻量灵活的 Python Web 应用框架。

Django

Django

6.1.2 · Windows

成熟的 Python Web 框架,适合构建内容站点和业务系统。

Spyder

Spyder

6.1.7 · Windows

面向科学计算与数据分析的 Python 集成开发环境。

SciPy

SciPy

1.18.1 · Windows

面向科学、工程和技术计算的 Python 算法库。