1. 使用jstack命令
- 检测方法:在应用运行时,通过
jstack <pid>
命令获取Java进程的线程转储信息(其中 <pid>
是目标Java进程的ID)。在输出信息中查找“Deadlock found”相关字样,若存在则表明发生了死锁,并会显示死锁涉及的线程及锁的信息。
- 优点:简单直接,不需要在代码中添加额外逻辑,适用于所有Java应用。
- 缺点:需要人工主动执行命令并分析结果,不能实时自动监控,若在获取线程转储时死锁短暂消失则可能检测不到。
- Java标准库工具:
jstack
是Java开发工具包(JDK)自带的命令行工具。
2. 使用ThreadMXBean
- 检测方法:通过
ThreadMXBean
的 findDeadlockedThreads()
方法,该方法返回一个 long[]
数组,包含死锁线程的ID。可以定时调用此方法,如在一个单独的线程中定期执行检测逻辑。示例代码如下:
import java.lang.management.ManagementFactory;
import java.lang.management.ThreadInfo;
import java.lang.management.ThreadMXBean;
public class DeadlockDetector {
private static final ThreadMXBean threadMXBean = ManagementFactory.getThreadMXBean();
public static void main(String[] args) {
Thread detectorThread = new Thread(() -> {
while (true) {
long[] deadlockedThreads = threadMXBean.findDeadlockedThreads();
if (deadlockedThreads != null) {
System.out.println("Deadlock detected:");
for (long threadId : deadlockedThreads) {
ThreadInfo threadInfo = threadMXBean.getThreadInfo(threadId);
System.out.println("Thread: " + threadInfo.getThreadName());
}
}
try {
Thread.sleep(5000); // 每5秒检测一次
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
detectorThread.setDaemon(true);
detectorThread.start();
// 主业务逻辑
}
}
- 优点:可以在应用内部实现自动化、实时检测,无需外部干预。
- 缺点:需要在代码中添加检测逻辑,可能对应用性能产生一定影响,尤其是频繁检测时。
- Java标准库工具:
java.lang.management.ThreadMXBean
接口及相关实现类。
3. 使用JConsole
- 检测方法:启动JConsole(在JDK的bin目录下),连接到目标Java进程。在“线程”标签页中,可以实时查看线程状态,若发生死锁,会有相应提示,并可查看死锁线程的详细信息。
- 优点:图形化界面,操作直观,能提供丰富的线程运行时信息,包括死锁情况。
- 缺点:需要启动额外工具并手动连接进程,不适用于生产环境自动化检测,且可能因网络等问题连接失败。
- Java标准库工具:JConsole是JDK自带的图形化监控工具。