获取Java线程id和堆栈跟踪的失控Java线程

在我最繁忙的生产安装中,有时我会得到一个似乎陷入无限循环的单个线程。 经过大量的研究和调试后,我还没弄清楚谁是罪魁祸首,但似乎应该是可能的。 以下是血腥的细节:

目前的调试说明:

1) ps -eL 18975向我展示了Linux pid问题子线程,19269

$ps -eL | grep 18975 ... PID LWP TTY TIME CMD 18975 18994 ? 00:00:05 java 18975 19268 ? 00:00:00 java 18975 19269 ? 05:16:49 java 18975 19271 ? 00:01:22 java 18975 19273 ? 00:00:00 java ... 

2) jstack -l 18975表示没有死锁, jstack -m 18975不起作用

3) jstack -l 18975确实为我的所有线程(~400)提供了堆栈跟踪。 示例线程堆栈( 而不是问题 ):

  “http-342.877.573.944-8080-360”守护程序prio = 10 tid = 0x0000002adaba9c00 nid = 0x754c in Object.wait()[0x00000000595bc000..0x00000000595bccb0]
    java.lang.Thread.State:WAITING(在对象监视器上)
         at java.lang.Object.wait(Native Method)
         - 等待(org.apache.tomcat.util.net.JIoEndpoint $ Worker)
        在java.lang.Object.wait(Object.java:485)
         at org.apache.tomcat.util.net.JIoEndpoint $ Worker.await(JIoEndpoint.java:416)
         - 已锁定(org.apache.tomcat.util.net.JIoEndpoint $ Worker)
        在org.apache.tomcat.util.net.JIoEndpoint $ Worker.run(JIoEndpoint.java:442)
        在java.lang.Thread.run(Thread.java:619)

4)ps -eL输出的线程ID与jstack的输出不匹配,或者至少我看不到它。 (jstack文档有点稀疏。)

5)没有繁重的IO,内存使用或其他相应的活动线索。

平台:

  • Java 6
  • 雄猫6
  • RHEL 4(64位)

有谁知道如何从linux ps输出到我的问题子java线程的连接? 如此接近,但到目前为止……

看起来jstack输出中的nid是Linux LWP id。

 "http-342.877.573.944-8080-360" daemon prio=10 tid=0x0000002adaba9c00 nid=0x754c in Object.wait() [0x00000000595bc000..0x00000000595bccb0] 

将nid转换为十进制,你有LWP id。 在你的情况下,0x754c是30028.这个过程没有显示在我们的ps输出中,但它可能是你省略了节省空间的LWP之一。

这里有一个Perl片段,可用于将jstack的输出传递给:

 #!/usr/bin/perl -w while (<>) { if (/nid=(0x[[:xdigit:]]+)/) { $lwp = hex($1); s/nid=/lwp=$lwp nid=/; } print; } 

您可以使用JConsole查看线程的堆栈跟踪。

如果您使用的是JDK 1.6.0_07或更高版本,则还可以使用visualvm 。

这两个工具都可以很好地查看应用程序中所有正在运行的线程。 visualvm相当好一点,但希望看到所有线程可以帮助你追踪失控的线程。

检查始终处于RUNNING状态的线程。 当我们有一个失控的线程时,堆栈跟踪会不断变化。 所以我们能够告诉循环调用哪些方法,并跟踪循环。

很好,有用的答案!

对于Linux,使用ps -efL,-L选项将显示LWP。 作为旁注,
“http-342.877.573.944-8080-360”守护进程prio = 10表示“ ThreadName (由JVM提供)” runningmode (inheritance自pid) 优先级 (inheritance自pid)

从内存中,如果在控制台上按CTRL-BREAK,您将获得当前线程的转储和一些堆栈跟踪帧。

从内存(我不确定这是一个IntelliJ IDEafunction,还是java中的默认function)但它会告诉你哪个线程死锁,以及它们正在等待哪个对象。 您应该能够将输出重定向到文件,只需grep查看DEADLOCKED文本。

JConsole,VisualVM或其他分析器(如JProfiler)也会向您显示线程及其堆栈,但是如果您不想使用任何外部工具,我认为CTRL-BREAK将为您提供所需的内容。

在SUN

请注意, prstat默认显示轻量级进程,而不是LWPID。

要查看特定用户的所有轻量级进程的信息,请使用-L选项。

 prstat -L -v -u weblogic 

现在使用LWPID并将其转换为hex,并将其与线程转储中的nid匹配