Несколько потоков застряли в нативных вызовах (Java) - PullRequest
5 голосов
/ 01 сентября 2008

У меня проблема с приложением, работающим на Fedora Core 6 с JDK 1.5.0_08.

Через некоторое время безотказной работы (обычно несколько дней) потоки начинают зависать в собственных методах.

Потоки заблокированы примерно так:

"pool-2-thread-2571" prio=1 tid=0x08dd0b28 nid=0x319e waiting for monitor entry [0xb91fe000..0xb91ff7d4]
at java.lang.Class.getDeclaredConstructors0(Native Method)

или

"pool-2-thread-2547" prio=1 tid=0x75641620 nid=0x1745 waiting for monitor entry [0xbc7fe000..0xbc7ff554]
at sun.misc.Unsafe.defineClass(Native Method)

Особенно озадачивает для меня это:

"HealthMonitor-10" daemon prio=1 tid=0x0868d1c0 nid=0x2b72 waiting for monitor entry [0xbe5ff000..0xbe5ff4d4]
at java.lang.Thread.dumpThreads(Native Method)
at java.lang.Thread.getStackTrace(Thread.java:1383)

Потоки остаются заблокированными до перезагрузки виртуальной машины.

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

Любые предложения или советы будут с благодарностью!

Спасибо, Дэвид

Ответы [ 5 ]

4 голосов
/ 30 сентября 2008

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

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

Я бы дополнительно выяснил, что происходит с загрузкой классов. Возможно, какой-то поток использует загрузчик классов для загрузки класса из сетевого расположения, которое является медленным / недоступным и, таким образом, блокируется в течение действительно длительного времени, не уступая монитор другим потокам, которые хотят загрузить класс. Исследование выходных данных при запуске JVM с -verbose: class может быть единственной попыткой.

2 голосов
/ 01 октября 2008

Несколько месяцев назад у меня были подобные проблемы, и я обнаружил, что утилита jthread (?) Неоценима. Вы даете ему идентификатор процесса для вашего Java-приложения, и он будет выгружать весь стек для каждого потока в вашем процессе.

Из вывода jthread я увидел, что один поток пытался получить блокировку после входа в монитор, а другой поток пытался войти в монитор после получения блокировки. Рецепт для тупика.

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

1 голос
/ 07 октября 2008

Можете ли вы узнать, какой поток фактически синхронизируется на мониторе, на котором ожидает собственный метод? По крайней мере, поток-дамп, который вы получаете от виртуальной машины при отправке ей SIGQUIT (kill -3), должен показывать эту информацию, как в

"Thread-0" prio=5 tid=0x0100b060 nid=0x84c000 waiting for monitor entry [0xb0c8a000..0xb0c8ad90]
    at Deadlock$1.run(Deadlock.java:8)
    - waiting to lock <0x255e5b38> (a java.lang.Object)
...
"main" prio=5 tid=0x01001350 nid=0xb0801000 waiting on condition [0xb07ff000..0xb0800148]
    at java.lang.Thread.sleep(Native Method)
    at Deadlock.main(Deadlock.java:21)
- locked <0x255e5b38> (a java.lang.Object)

В дампах, которые вы опубликовали до сих пор, я не вижу ни одной темы, которая действительно ожидает блокировки определенного монитора ...

0 голосов
/ 15 февраля 2011

Я нашел этот поток после того, как столкнулся с той же проблемой - JDK 1.6.0_23, работающий в Linux с Tomcat 6.0.29. Хотя я не уверен, что эти биты актуальны, но я заметил, что помимо того, что многие потоки «зависли» в собственном методе getDeclaredConstructors (), процессор был на 100% для процесса java. Таким образом, все потоки запросов застряли здесь, процессор на 100%, дампы потоков не показывают никаких взаимоблокировок (и никакие другие потоки не выполняют каких-либо существенных действий), он пах для меня как колотящий сборщик мусора. Конечно же, проверил журналы сервера и были многочисленные ошибки OutOfMemory - пространство кучи было исчерпано.

Не могу сказать, что это будет основной причиной зависания потоков каждый раз, но, надеюсь, информация здесь поможет другим, по крайней мере, исключить это как возможную причину ...

0 голосов
/ 01 сентября 2008

Возможно, вам следует использовать другую версию JDK.
Для вашего "загадочного" есть запись об ошибке для 1.5.0_08. Сообщается об утечке памяти (не знаю, связано ли это с вашей проблемой):
http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6469701

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

...