Как отлаживать ошибки, возникающие в JVM при запуске моего кода? - PullRequest
16 голосов
/ 31 августа 2011

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

Я отлаживал программы на C в gdb, и я отлаживал код Java из своей IDE. Я не уверен, как подходить к C-подобным сбоям в работающей Java-программе.

Я предполагаю, что я не смотрю на ошибку JVM здесь. Другие программы на Java работают просто отлично, и JVM от Sun, вероятно, более стабильна, чем мой код. Тем не менее, я понятия не имею, как я мог вызвать segfaults с кодом Java. Там определенно достаточно свободной памяти, и когда я последний раз проверял в профилировщике, использование кучи составляло около 50%, а случайные скачки - около 80%. Есть ли параметры запуска, которые я мог бы исследовать? Что такое хороший контрольный список при обнаружении такой ошибки?

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

ETA: некоторые кровавые детали

(Я ищу общий подход, поскольку реальная проблема может быть очень конкретной. Тем не менее, есть некоторая информация, которую я уже собрал, и она может иметь некоторое значение.)

Некоторое время назад у меня возникли похожие проблемы после обновления моего CI-сервера (подробнее см. здесь ), но это исправление (настройка -XX:MaxPermSize) на этот раз не помогло.

Дальнейшее расследование показало, что в файлах журнала сбоев поток, помеченный как «текущий поток», никогда не принадлежит моему, но либо с именем «VMThread», либо с именем «GCTaskThread» - если он последний, он дополнительно помечен с комментарием «(выход)», если он первый, GCTaskThread отсутствует в списке. Это заставляет меня предположить, что проблема может быть в конце операции GC.

Ответы [ 5 ]

23 голосов
/ 08 сентября 2011

Я предполагаю, что я не смотрю на ошибку JVM здесь.Другие программы на Java работают просто отлично, и JVM от Sun, вероятно, более стабильна, чем мой код.

Я не думаю, что вы должны делать это предположение.Без использования JNI вы не сможете писать код Java, который вызывает SIGSEGV (хотя мы знаем, что это происходит).Я хочу сказать, что когда это происходит, это либо ошибка в JVM (не неслыханная), либо ошибка в некотором коде JNI.Если у вас нет JNI в вашем собственном коде, это не значит, что вы не используете какую-то библиотеку, так что ищите это.Когда я уже сталкивался с подобными проблемами, это было в библиотеке манипуляций с изображениями.Если виновник не в вашем собственном коде JNI, вы, вероятно, не сможете «исправить» ошибку, но вы все равно сможете ее обойти.

Во-первых, вы должны получить альтернативуJVM на той же платформе и попытаться воспроизвести его.Вы можете попробовать одну из этих альтернатив .

Если вы не можете воспроизвести ее, скорее всего, это ошибка JVM.Исходя из этого, вы можете назначить конкретную JVM или выполнить поиск в базе данных ошибок , используя то, что вы знаете о том, как ее воспроизвести, и, возможно, получить предлагаемые обходные пути.(Даже если вы можете воспроизвести его, многие реализации JVM являются просто изменениями в реализации Oracle Hotspot, поэтому это может быть ошибка JVM.)

Если вы можете воспроизвести его с альтернативной JVM, ошибка может быть, у вас есть какая-то ошибка JNI.Посмотрите, какие библиотеки вы используете и какие нативные вызовы они могут делать.Иногда существуют альтернативные конфигурации «чистого Java» или файлы jar для той же библиотеки или альтернативные библиотеки, которые делают почти то же самое.

Удачи!

9 голосов
/ 08 сентября 2011

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

  1. Запустите Java-программу в отладчике Java, с точкой останова задолго до возможного sigsegv.
  2. Используйте команду ps для получения processid из Java.
  3. gdb / usr / lib / jvm / sun-java6 / bin / java processid
  4. убедитесь, что команда gdb 'handle' остановлена ​​на SIGSEGV
  5. продолжить в отладчике java източка останова.
  6. ожидание взрыва.
  7. Используйте gdb для расследования

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

2 голосов
/ 14 сентября 2011

Я нашел хороший список на http://www.oracle.com/technetwork/java/javase/crashes-137240.html. Поскольку я получаю сбои во время GC, я попробую переключиться между сборщиками мусора.

Я попытался переключиться между последовательным и параллельным GC (последний используется по умолчанию на 64-битном сервере Linux), это только соответственно изменило сообщение об ошибке.

Уменьшение максимального размера кучи с 16 ГБ до 10 ГБ после нового анализа в профилировщике (что дало мне уменьшение использования кучи при 8 ГБ) привело к значительному уменьшению занимаемой площади виртуальной памяти (16 ГБ вместо 60), но Я даже не знаю, что это значит, и Интернет говорит, что это не имеет значения.

В настоящее время JVM работает в режиме клиента (при использовании опции запуска -client, таким образом, переопределяется значение по умолчанию -server). Пока что сбоев нет, но влияние на производительность кажется довольно значительным.

0 голосов
/ 13 декабря 2017

Попробуйте проверить, не знает ли программа c carsh, которая вызвала java crash.use valgrind, неверный, а также проверить размер стека.

0 голосов
/ 14 сентября 2011

Если у вас есть corefile, вы можете попробовать запустить на нем jstack, что даст вам что-то более понятное - см. http://download.oracle.com/javase/6/docs/technotes/tools/share/jstack.html,, хотя, если это ошибка в потоке gc, это может быть не очень полезно.

...