Получение идентификатора потока Java и трассировки стека запущенного потока Java - PullRequest
17 голосов
/ 21 октября 2008

В моей самой загруженной производственной установке иногда я получаю один поток, который кажется застрявшим в бесконечной петле. Мне не удалось выяснить, кто является виновником, после долгих исследований и отладки, но кажется, что это должно быть возможно. Вот кровавые детали:

Текущие примечания по отладке:

1) ps -eL 18975 показывает мне pid Linux, проблемный дочерний поток, 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" daemon prio=10 tid=0x0000002adaba9c00 nid=0x754c in Object.wait() [0x00000000595bc000..0x00000000595bccb0]
   java.lang.Thread.State: WAITING (on object monitor)
        at java.lang.Object.wait(Native Method)
        - waiting on  (a org.apache.tomcat.util.net.JIoEndpoint$Worker)
        at java.lang.Object.wait(Object.java:485)
        at org.apache.tomcat.util.net.JIoEndpoint$Worker.await(JIoEndpoint.java:416)
        - locked  (a org.apache.tomcat.util.net.JIoEndpoint$Worker)
        at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:442)
        at java.lang.Thread.run(Thread.java:619)

4) Идентификатор потока вывода ps -eL не совпадает с выводом из jstack, или, по крайней мере, я его не вижу. (документация jstack немного скудна.)

5) Не требуется интенсивного ввода-вывода, использования памяти или других соответствующих подсказок для работы.

Платформа:

  • Java 6
  • Tomcat 6
  • RHEL 4 (64-разрядная версия)

Кто-нибудь знает, как я могу установить это соединение из вывода linux ps в мой проблемный дочерний поток Java? Так близко, но так далеко ...

Ответы [ 5 ]

13 голосов
/ 29 июля 2009

Похоже, что nid в выводе jstack является идентификатором LWP Linux.

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

Преобразуйте nid в десятичную, и у вас будет идентификатор LWP. В вашем случае 0x754c - 30028. Этот процесс не показан в нашем выводе ps, но, вероятно, это был один из LWP, который вы пропустили для экономии места.

Вот небольшой фрагмент Perl, который вы можете использовать для передачи вывода jstack:

#!/usr/bin/perl -w
while (<>) {
    if (/nid=(0x[[:xdigit:]]+)/) {
        $lwp = hex($1);
        s/nid=/lwp=$lwp nid=/;
    }
    print;
}
7 голосов
/ 21 октября 2008

Вы можете использовать JConsole для просмотра трассировки стека потока.

Если вы используете JDK 1.6.0_07 или выше, вы также можете использовать visualvm .

Оба инструмента обеспечивают хороший обзор всех запущенных потоков в приложении. Visualvm немного лучше, но, надеюсь, просмотр всех потоков поможет вам отследить оставшийся поток.

Проверьте наличие потоков, которые всегда в состоянии RUNNING. Когда у нас был резервный поток, трассировка стека постоянно менялась. Таким образом, мы смогли определить, какие методы вызывал цикл, и отследить цикл.

1 голос
/ 30 марта 2012

Хорошие, полезные ответы!

Для Linux используйте ps -efL, опция -L покажет LWP. Как примечание стороны,
"http-342.877.573.944-8080-360" демон prio = 10 означает " ThreadName (согласно JVM)" runningmode (унаследовано от pid) priority (унаследовано от pid)

0 голосов
/ 25 ноября 2009

В СОЛНЦЕ

Обратите внимание, что prstat по умолчанию показывает количество процессов, не связанных с малым весом, а не LWPID.

Чтобы просмотреть информацию обо всех упрощенных процессах для конкретного пользователя, используйте параметр -L.

prstat -L -v -u weblogic

теперь используйте LWPID, конвертируйте его в шестнадцатеричный код и сопоставьте его с nid из дампа потока

0 голосов
/ 22 октября 2008

Из памяти, если вы нажмете CTRL-BREAK на консоли, вы получите дамп текущих потоков и несколько их кадров трассировки стека.

Из памяти (я не уверен, является ли это функцией IntelliJ IDEa или по умолчанию в java), но она скажет вам, какой поток заблокирован и какой объект они ожидают. Вы должны быть в состоянии перенаправить вывод в файл и просто использовать grep для текста DEADLOCKED.

JConsole, VisualVM или другие профилировщики, такие как JProfiler, также покажут вам потоки и их стеки, однако, если вы не хотите использовать какой-либо внешний инструмент, я думаю, что CTRL-BREAK даст вам то, что вы ищете.

...