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

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

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

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

Необычные данные В этом случае я вижу все виды классов / методов заблокированными,включая внутренние классы 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)

1 Ответ

17 голосов
/ 25 октября 2010

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

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