Подтвердить что ты не робот

Проблема блокировки Java: почему JVM блокирует потоки во многих разных классах/методах?

Обновление: Это похоже на проблему с памятью. Файл Hprof с оценкой 3.8 Гб показал, что JVM была демпинг-кучей, когда эта "блокировка" произошла. Наша операционная группа увидела, что сайт не отвечает, берет трассировку стека, а затем закрывает экземпляр. Я считаю, что они закрыли сайт до завершения кучи. В журнале были нет ошибки/исключения/доказательства проблем - вероятно, из-за того, что JVM был убит, прежде чем он смог создать сообщение об ошибке.

Оригинальный вопрос У нас была недавняя ситуация, когда приложение появилось - конечному пользователю - повесить. Мы получили трассировку стека перед перезагрузкой приложения, и я нашел некоторые неожиданные результаты: из 527 потоков, 463 - состояние потока BLOCKED.

В прошлом В прошлом блокированный поток обычно имел эту проблему: 1) некоторые очевидные узкие места: например. некоторая блокировка записи базы данных или проблема блокировки файловой системы, из-за чего другие потоки ждут. 2) Все заблокированные потоки будут блокироваться одним и тем же классом/методом (например, кластер jdbc или файловой системы)

Необычные данные В этом случае я вижу всевозможные классы/методы, блокированные, в том числе внутренние классы jvm, классы jboss, log4j и т.д., Помимо классов приложений (включая вызовы jdbc и lucene)

Вопрос  что может вызвать JVM для блокировки log4j.Hierarchy.getLogger, java.lang.reflect.Constructor.newInstance? Очевидно, что какой-то ресурс "скуден", но какой ресурс?

спасибо

будет

Отрывки трассировки стека

http-0.0.0.0-80-417" daemon prio=6 tid=0x000000000f6f1800 nid=0x1a00 waiting for monitor entry [0x000000002dd5d000]
   java.lang.Thread.State: BLOCKED (on object monitor)
                at sun.reflect.GeneratedConstructorAccessor68.newInstance(Unknown Source)
                at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:27)
                at java.lang.reflect.Constructor.newInstance(Constructor.java:513)
                at java.lang.Class.newInstance0(Class.java:355)
                at java.lang.Class.newInstance(Class.java:308)
                at org.jboss.ejb.Container.createBeanClassInstance(Container.java:630)

http-0.0.0.0-80-451" daemon prio=6 tid=0x000000000f184800 nid=0x14d4 waiting for monitor entry [0x000000003843d000]
   java.lang.Thread.State: BLOCKED (on object monitor)
                at java.lang.Class.getDeclaredMethods0(Native Method)
                at java.lang.Class.privateGetDeclaredMethods(Class.java:2427)
                at java.lang.Class.getMethod0(Class.java:2670)

"http-0.0.0.0-80-449" daemon prio=6 tid=0x000000000f17d000 nid=0x2240 waiting for monitor entry [0x000000002fa5f000]
   java.lang.Thread.State: BLOCKED (on object monitor)
                at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.register(Http11Protocol.java:638)
                - waiting to lock <0x00000007067515e8> (a org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler)
                at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.createProcessor(Http11Protocol.java:630)


"http-0.0.0.0-80-439" daemon prio=6 tid=0x000000000f701800 nid=0x1ed8 waiting for monitor entry [0x000000002f35b000]
   java.lang.Thread.State: BLOCKED (on object monitor)
                at org.apache.log4j.Hierarchy.getLogger(Hierarchy.java:261)
                at org.apache.log4j.Hierarchy.getLogger(Hierarchy.java:242)
                at org.apache.log4j.LogManager.getLogger(LogManager.java:198)
4b9b3361

Ответ 1

Они перечислены примерно в том порядке, в котором я буду их проверять, в зависимости от собранных доказательств:

  • Вы посмотрели на поведение GC? Вы под давлением памяти? Это может привести к тому, что newInstance() и некоторые другие выше будут заблокированы. Запустите свою виртуальную машину с помощью -XX:+PrintGCDetails -XX:+PrintGCTimeStamps -verbose:gc и запишите выход. Вы наблюдаете чрезмерное время GC около времени сбоя/блокировки?
    • Является ли условие повторяемым? Если да, попробуйте с различными размерами кучи в JVM (-Xmx) и посмотрите, существенно ли изменяется поведение. Если это так, найдите утечку памяти или правильно размер кучи для вашего приложения.
    • Если предыдущий жесткий, и вы не получаете OutOfMemoryError, когда хотите, вы можете настроить GC-переходы... см. JDK6. 0 XX опций или JDK6.0 GC Tuning Whitepaper. Посмотрите конкретно на -XX:+UseGCOverheadLimit и -XX:+GCTimeLimit и соответствующие параметры. (обратите внимание, что они плохо документированы, но могут быть полезны...)
  • Может ли быть тупик? С помощью только выдержек трассировки стека здесь не может быть определено. Посмотрите на циклы среди мониторов, которые блокируют потоки (по сравнению с тем, что они держат). Я полагаю, что jconsole может сделать это для вас... (yep, под вкладкой threads, "обнаружить тупики" )
  • Попробуйте выполнить несколько повторяющихся стеков > и посмотрите, какие изменения в сравнении с тем, что остается тем же...
  • Сделайте судебно-медицинскую экспертизу... для каждой записи в стеке, которая говорит "БЛОКИРОВАТЬ", ищите нужную строку кода и выясните, есть ли там монитор или нет. Если есть фактическое наблюдение за монитором, должно быть достаточно легко определить предельный ресурс. Однако некоторые из ваших потоков могут быть заблокированы без прозрачного монитора, это будет сложнее...