2008-09-01 2 views
5

У меня проблема с приложением, запущенным на Fedora Core 6 с JDK 1.5.0_08.Несколько потоков, вставленных в собственные вызовы (Java)

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

Нити фиксируются в чем-то вроде этого:

"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) 

нити не застревают до VM перезапускается.

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

Любые предложения или рекомендации будут очень благодарны!

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

ответ

0

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

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

+0

Если не я может доказать, что проблема вызвана ошибкой в ​​версии JDK, которая была исправлена ​​позже, обновление JDK не является вариантом. Завтра я попытаюсь найти исходный код - надеюсь, это может дать мне некоторое представление о проблеме. Хотя я действительно помню, что дамп потока «смешанный родной/Java», который показал собственные следы стека JDK и не мог ничего увидеть там ... Я работаю на Linux, поэтому он не похож на ошибка, с которой вы связаны. – 2014-03-01 09:08:15

4

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

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

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

2

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

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

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

+1

Я думаю, что имя инструмента jstack; Я использовал его для информации о потоках выше. Кроме того, отправка SIGQUIT (ctrl - \\) в JVM сбрасывает потоки в stdout. Моя проблема заключается в том, что кажется, что тупик происходит из-за моего контроля (собственный код). Хотя я не сомневаюсь, что я держу замок как-то ... – 2008-10-02 07:26:58

1

Можете ли вы узнать, какая нить фактически синхронизируется на мониторе, на котором ожидает метод native? По крайней мере, нить-свалка вы получаете от VM, когда вы посылаете ему SIGQUIT (убить -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) 

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

+0

Я думаю, что вы правы в этом, связанном с загрузкой классов. Хотя потоки всегда блокируют собственные методы, поэтому я не думаю, что это совпадение. Нет классов, которые могут занять много времени (или быть недоступными). Путь к классу включает только локальные банки. На самом деле существует более одного загрузчика классов, каждый из которых может конкурировать за некоторый ресурс и в результате блокироваться. Поскольку использование Groovy было удалено из приложения (это вызвало утечку памяти в PermGen), мы не видели никаких дополнительных случаев блока. Так что это может быть причиной проблемы. – 2008-10-02 08:19:48

0

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

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