17

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

当前调试说明:

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、内存使用或其他相应的活动线索可供使用。

平台:

  • 爪哇 6
  • 雄猫 6
  • RHEL 4(64 位)

有人知道我如何从 linux ps 输出到我的问题子 java 线程建立连接吗?这么近,又这么远……

4

5 回答 5

13

看起来 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;
}
于 2009-07-29T09:53:04.977 回答
7

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

如果您使用 JDK 1.6.0_07 或更高版本,您也可以使用visualvm

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

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

于 2008-10-21T14:47:20.823 回答
1

很好,有用的答案!

对于 Linux,使用 ps -efL,-L 选项将显示 LWP。附带说明一下,
“http-342.877.573.944-8080-360”守护进程 prio=10表示“ ThreadName(由 JVM 给出)”运行模式(继承自 pid)优先级(继承自 pid)

于 2012-03-30T14:03:14.900 回答
0

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

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

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

于 2008-10-22T03:31:14.043 回答
0

在太阳

请注意,prstat默认情况下显示轻量级进程的数量,而不是 LWPID。

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

prstat -L -v -u weblogic

现在使用 LWPID 并将其转换为十六进制并将其与线程转储中的 nid 匹配

于 2009-11-25T16:13:59.833 回答