2010-09-17 40 views
9

我有一个多线程应用程序。几条消息到达应用程序,并在分离的线程中处理。为此,我使用java.util.concurrent包中的ThreadPoolExecutor和FutureTask类。如何获取线程的堆栈跟踪

偶尔我在应用程序中有一些死锁。当发生死锁时,我想中断阻塞线程,并且我想记录此线程的堆栈跟踪,以便稍后解决死锁问题。

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

+0

你的意思是你想检测死锁并恢复?从来没有这样做过,但使用堆栈跟踪听起来并不像我正确的方式.. – 2010-09-17 11:01:26

+0

我需要堆栈跟踪,以便我知道线程卡住的位置,并且可以解决问题,以便应用程序可以正常工作重新开始。不过,我想中断阻塞线程,以便应用程序可以工作,直到找到一些时间来解决问题并释放它。 – Palo 2010-09-17 11:10:38

回答

5

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

+5

在UNIX环境中,向java进程发送“QUIT”('kill -QUIT ')信号也会将堆栈跟踪输出到标准输出。 – Bombe 2010-09-17 13:25:45

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); 
    } 
} 

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

0

我不知道,如果你想从同一个JVM或外部内获得堆栈跟踪,但如果你想获得与外部工具堆栈跟踪,下面会有所帮助:

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

您使用JStack。这里有一个很好的blog entry,详细介绍了如何获取堆栈跟踪。

4

进入僵局区域之前,设置一个字段一样,

thread = Thread.currentThread(); 

在你的监视线程可以执行thread.getStackTrace();获得该线程的堆栈跟踪在任何时间。

0

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

可以实现周期性任务检查死锁(其中死锁是Java的内在或Lock为主)和呼叫interrupt涉及场景中涉及的所有线程。但是,这并不能保证它能解决你的问题。它可能会再次发生。有关详细信息,请参见Dr Heinz's article on a deadlock detector

如果事实上,并不能保证interrupt甚至可以释放像这样的阻止进程。例如,通过使用超时和重试策略的锁定或“在您购买之前尝试”方法,它首先可以更好地避免死锁情况。

,我想记录该线程的堆栈跟踪...

如果你想这样做编程,再次,遵守亨氏博士的例子。如果没有,只要在发现问题时生成线程转储。

有什么办法,我们如何找到Java线程之外的线程的堆栈跟踪?

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