获取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:等待(在对象监视器上)
        在java.lang.Object.wait(本地方法)
        -等待(org.apache.tomcat.util.net.JIoEndpoint $ Worker)
        在java.lang.Object.wait(Object.java:485)
        在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
  • Male cat 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;
}