JVM падает под напряжением на RHEL 5.2

у меня есть (в настоящее время последний) JDK 1.6.0.18 сбой при запуске веб-приложения (в настоящее время последний) tomcat 6.0.24 неожиданно после от 4 до 24 часов 4 часа до 8 дней стресс-тестирования (30 потоков, попадающих в приложение на 6 mil. просмотров страниц/День). Это на RHEL 5.2 (Тиканга).

отчет о крушении на http://pastebin.com/f639a6cf1 и последовательный части аварии:

  • являться SIGSEGV-это быть брошенным
  • на libjvm.так что
  • eden пространство всегда заполнено (100%)

JVM работает со следующими параметрами:

CATALINA_OPTS="-server -Xms512m -Xmx1024m -Djava.awt.headless=true"

Я также протестировал память для аппаратных проблем с помощью http://memtest.org/ в течение 48 часов (14 проходов всей памяти) без каких-либо ошибок.

Я включен -verbose:gc -XX:+PrintGCDetails -XX:+PrintGCTimeStamps для проверки любых тенденций GC или истощения пространства, но там нет ничего подозрительного. GC и полный GC происходят на предсказуемые интервалы, почти всегда освобождающие одинаковый объем памяти.

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

есть идеи, где я должен искать дальше?

Edit-дополнительная информация:

1) в этом JDK нет клиентской виртуальной машины:

[foo@localhost ~]$ java -version -server
java version "1.6.0_18"
Java(TM) SE Runtime Environment (build 1.6.0_18-b07)
Java HotSpot(TM) 64-Bit Server VM (build 16.0-b13, mixed mode)

[foo@localhost ~]$ java -version -client
java version "1.6.0_18"
Java(TM) SE Runtime Environment (build 1.6.0_18-b07)
Java HotSpot(TM) 64-Bit Server VM (build 16.0-b13, mixed mode)

2) Изменение O / S невозможно.

3) я не хочу изменять переменные стресс-теста JMeter, так как это может скрыть проблему. Поскольку у меня есть прецедент (текущий сценарий стресс-теста), который разбивает JVM, я хотел бы исправить сбой и не изменять тест.

4) я сделал статический анализ на моем заявлении, но ничего серьезного не придумали.

5) память не растет с течением времени. Использование памяти уравновешивается очень быстро (после запуска) при очень устойчивой тенденции, которая не кажется подозрительной.

6) /var/log/messages не содержит никакой полезной информации перед или во время аварии

Подробнее: забыл упомянуть, что был apache (2.2.14), противостоящий tomcat с использованием mod_jk 1.2.28. Прямо сейчас я запускаю тест без apache на случай, если сбой JVM связан с собственным кодом mod_jk, который подключается к JVM (Tomcat connector).

после этого (если JVM снова вылетит) я попытаюсь удалить некоторые компоненты из моего приложения (кэширование, lucene, quartz), а затем попытаюсь использовать jetty. После аварии в настоящее время происходит в любое время от 4 часов до 8 дней, может потребоваться много времени, чтобы узнать, что происходит.

7 ответов


у вас есть выход компилятора? т. е. PrintCompilation (и если вы чувствуете себя особенно храбрым, LogCompilation).

Я отладил такой случай в части, наблюдая, что делает компилятор, и, в конце концов (это заняло много времени до момента лампочки), понимая, что мой сбой был вызван компиляцией определенного метода в драйвере oracle jdbc.

в основном то, что я бы сделал это;

  • переключатель на PrintCompilation
  • поскольку это не дает временных меток, напишите сценарий, который смотрит этот файл журнала (например, сон каждую секунду и печатает новые строки) и сообщает, когда методы были скомпилированы (или нет)
  • повторите тест
  • проверьте вывод компилятора, чтобы увидеть, соответствует ли сбой компиляции некоторого метода
  • повторите еще несколько раз, чтобы увидеть, есть ли шаблон

Если есть закономерности, то использовать .hotspot_compiler (или .hotspotrc), чтобы остановить компиляцию оскорбительного метода(ов), повторите тест и посмотрите, не взорвется ли он. Очевидно, в вашем случае этот процесс теоретически может занять месяцы, я боюсь.

ссылки

другая вещь, которую я бы сделал, это систематически изменять алгоритм gc, который вы используете и проверьте время сбоя против активности gc (например, коррелирует ли он с молодым или старым gc, как насчет TLABs?). Ваш дамп указывает, что вы используете параллельную очистку, поэтому попробуйте

  • серийный (молодой) коллектор (IIRC его можно совместить с параллельным старым)
  • ParNew + CMS
  • G1

если он не повторяется с разными GC algos, то вы знаете, что это до этого (и у вас нет исправления, кроме как изменить GC algo и/или пройти через старые JVMs, пока не найдете версию этого algo, которая не взорвется).


несколько идей:

  • используйте другую версию JDK, Tomcat и/или OS
  • слегка изменить параметры теста, например 25 потоков на 7.2 м просмотров страниц / День
  • монитор или использование памяти профиля
  • отладка или настройка сборщика мусора
  • выполнить статический и динамический анализ

вы пробовали другое оборудование? Похоже, вы используете 64-разрядную архитектуру. По моему собственному опыту 32-бит быстрее и стабильнее. Возможно, где-то есть проблема с оборудованием. Время "между 4-24 часами" довольно распространено, чтобы быть просто проблемой программного обеспечения. Хотя вы говорите, что в системном журнале нет ошибок, поэтому я могу быть далеко. Все еще думаю, что стоит попробовать.


ваша память растет с течением времени? Если это так, я предлагаю изменить пределы памяти ниже, чтобы увидеть, если система терпит неудачу чаще, когда память исчерпана.

можете ли вы воспроизвести проблему быстрее, если:

  • вы уменьшаете доступную память для JVM?
  • вы уменьшаете доступные системные ресурсы (т. е. истощаете системную память, поэтому JVM не хватает)
  • вы меняете варианты использования на более простые модель?

одна из основных стратегий, которые я использовал, - определить, какой вариант использования вызывает проблему. Это может быть общая проблема, или это может быть конкретный вариант использования. Попробуйте зарегистрировать запуск и остановку вариантов использования, чтобы определить, какие варианты использования могут вызвать проблему. Если вы разделите свои варианты использования пополам, посмотрите, какая половина не работает быстрее. Это, вероятно, будет более частой причиной неудачи. Естественно, проведение нескольких испытаний каждого конфигурация увеличит точность ваших измерений.

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

удачи, Якоб!--1-->


попробуйте переключить контейнер сервлета с Tomcat на Jetty http://jetty.codehaus.org/jetty/.


на вашем месте я бы сделал следующее:

  • попробуйте немного более старые версии Tomcat/JVM. Вы, кажется, управляете новейшим и величайшим. Я бы спустился на две версии или около того, возможно, попробую JRockit JVM.
  • сделайте дамп потока (kill -3 java_pid), пока приложение работает, чтобы увидеть полные стеки. Ваш текущий дамп показывает, что многие потоки блокируются , но неясно, где они блокируют (ввод-вывод? какое-то внутреннее голодание? что-нибудь еще?). Я бы даже, возможно, запланировал убить -3 для запуска каждую минуту, чтобы сравнить любой случайный дамп потока с тем, что непосредственно перед сбоем.
  • Я видел случаи, когда Linux JDK просто умирает, тогда как Windows JDK может изящно поймать исключение (тогда было StackOverflowException), поэтому, если вы можете изменить код, добавьте "catch Throwable" где-то в верхнем классе. На всякий случай.
  • играть с параметрами настройки GC. Включение/выключение параллельного GC, настройка NewSize / MaxNewSize. И да, это не научно - довольно отчаянная потребность в рабочем решении. Более подробная информация здесь: http://java.sun.com/javase/technologies/hotspot/gc/gc_tuning_6.html

дайте нам знать, как в этом разобрались!


есть ли возможность перейти к 32-битной JVM вместо этого? Я считаю, что это самое зрелое подношение от Солнца.