如何获得线程的堆栈跟踪

时间:2010-09-17 10:54:00

标签: java multithreading deadlock stack-trace

我有一个多线程应用程序。有几条消息即将发送到应用程序,并在分离的线程中处理。为此,我使用包java.util.concurrent中的类ThreadPoolExecutor和FutureTask。

我偶尔会在应用程序中遇到一些死锁。当发生死锁时我想中断阻塞线程,我想记录这个线程的堆栈跟踪,以便以后可以解决死锁。

有没有什么办法可以在Java中找到该线程之外的线程的堆栈跟踪?

6 个答案:

答案 0 :(得分:5)

请参阅here了解如何生成堆栈跟踪,包括如何以编程方式执行此操作。在控制台中, Ctrl + Break 会将堆栈跟踪转储到stdout。有关详细信息,另请参阅this SO question

答案 1 :(得分:5)

您可以在应用程序中不时记录所有线程的堆栈跟踪(或在杀死进程之前)。要做到这一点:

Map<Thread, StackTraceElement[]> m = Thread.getAllStackTraces();
for(Map.Entry<Thread,  StackTraceElement[]> e : m.entrySet()) {
    log(e.getKey().toString());
    for (StackTraceElement s : e.getValue()) {
        log("  " + s);
    }
}

当运行夜间自动化测试时,有时一些测试用例会陷入僵局。我添加了一个等待30分钟的“TimeBomb”守护程序线程,然后如上所述记录所有堆栈跟踪。

答案 2 :(得分:4)

在进入死锁区域之前,请设置一个字段,如

thread = Thread.currentThread();

在监控线程中,您可以执行thread.getStackTrace();以随时获取该线程的堆栈跟踪。

答案 3 :(得分:2)

您使用JStack。这是一个很好的blog entry,它详细说明了如何获得堆栈跟踪。

答案 4 :(得分:0)

我不确定您是希望从同一JVM内部还是外部获取堆栈跟踪,但如果您希望使用外部工具获取堆栈跟踪,以下内容将有所帮助:

  • The Java VisualVM工具可用于连接到正在运行的JVM,其中可以转储线程堆栈。对于大多数使用Java 6的人来说,这通常是首选方法。启动VisualVM后,可以通过在“应用程序”选项卡中选择进程来获取进程的线程转储。现在,“线程”选项卡可用于查看正在运行的进程中的线程,在同一选项卡中,您将找到“线程转储”按钮以提取所需信息。
  • JDK中的jstack实用程序也可用于生成线程堆栈跟踪。

答案 5 :(得分:0)

  

发生死锁时我想中断阻塞线程......

可以实现一个周期性任务来检查死锁(其中死锁是java内在的或基于Lock)并在方案中涉及的所有线程上调用interrupt。但是,这并不能保证它能解决您的问题。它可能会再次发生。有关详细信息,请参阅Dr Heinz's article on a deadlock detector

如果确实如此,则无法保证interrupt甚至可以释放这样的被阻止进程。它是一种更好的方法,可以首先避免死锁情况,例如,使用具有超时和重试策略的锁定或“先尝试购买”方法。

  

我想记录这个线程的堆栈跟踪......

如果您想以编程方式执行此操作,请再次按照Heinz博士的示例进行操作。如果没有,只需在发现问题时生成线程转储。

  

有没有什么办法可以在Java中找到该线程之外的线程的堆栈跟踪?

是和否。您可以从其他VM转储线程,但是它们的堆栈跟踪可能没有您想象的那样有用于确定死锁的原因。如果检测到真正的死锁(由JVM本身在您的应用程序VM的线程转储上),您应该拥有调试原因所需的一切(或多或少)。