Получение идентификатора потока Java и трассировки стека Java-потока
В моей самой загруженной производственной установке иногда я получаю один поток, который, кажется, застревает в бесконечном цикле. Мне не удалось выяснить, кто является виновником, после долгих исследований и отладки, но похоже, что это должно быть возможно. Вот детали gory:
Текущие примечания по отладке:
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" 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 проблемы? Так близко, но пока...
Ответы
Ответ 1
Похоже, что nid в выводе jstack - это идентификатор Linux LWP.
"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;
}
Ответ 2
Вы можете использовать JConsole для просмотра трассировки стека потоков.
Если вы используете JDK 1.6.0_07 или выше, вы также можете использовать visualvm.
Оба инструмента обеспечивают прекрасный обзор всех запущенных потоков в приложении. Визуальный эффект довольно приятный, но, надеюсь, все потоки помогут вам отследить нисходящий поток.
Проверьте наличие потоков, которые всегда находятся в состоянии RUNNING. Когда у нас была бегущая нить, трассировка стека постоянно менялась. Таким образом, мы смогли определить, какие методы вызывал цикл, и отслеживать цикл.
Ответ 3
Приятные, полезные ответы!
Для Linux используйте ps -efL, -L опция покажет LWP.
В качестве примечания,
"http-342.877.573.944-8080-360" daemon prio = 10 означает
"ThreadName (как указано JVM)" приоритет runningmode (унаследованный от pid) (унаследованный от pid)
Ответ 4
Из памяти, если вы CTRL-BREAK на консоли, вы получите дамп текущих потоков и несколько их кадров трассировки стека.
Из памяти (я не уверен, что это функция IntelliJ IDEa, или она по умолчанию в java), но она сообщит вам, какой поток зашел в тупик, и какой объект они ждут. Вы должны иметь возможность перенаправить вывод в файл и просто grep для текста DEADLOCKED.
JConsole, VisualVM или другие профилировщики, такие как JProfiler, также покажут вам потоки и их стеки, однако, если вы не хотите использовать какой-либо внешний инструмент, я думаю, что CTRL-BREAK даст вам то, что вы ищете.
Ответ 5
В SUN
Обратите внимание, что prstat
по умолчанию показывает отсутствие легких процессов, а не LWPID.
Чтобы просмотреть информацию о всех легких процессах для конкретного пользователя, используйте параметр -L
.
prstat -L -v -u weblogic
теперь используйте LWPID и преобразуйте его в шестнадцатеричный и сопоставьте его с nid из дампа потока