Файл hs_err_pid.log не создан и ядро ​​выгружено из jvm в Solaris - PullRequest
6 голосов
/ 26 сентября 2011

Описание проблемы

Через некоторое время работы моего приложения на Java-сервере я испытываю странное поведение виртуальной машины Oracle Java на Solaris.Обычно, когда происходит сбой файла jvm hs_err_pid.log, создается файл (местоположение определяется параметром -XX:ErrorFile jvm, как описано здесь: Как я могу подавить создание файла hs_err_pid?

Но в моем случае файл не был создан, остался только файл дампа ядра core.

Используя стандартные инструменты Solaris pstack и pflags, я смог собрать больше информациио сбое (которое включено ниже) из файла core.

Пробные решения

  • Попытка найти все файлы hs_err_pid.logчерез файловую систему, но ничего не может быть найдено (даже вне рабочего каталога приложения), т.е.:

    find / -name "hs_err_pid*"

  • Я пытался найти ошибки jvm, связанные сjvm, но я не смог найти ничего интересного, похожего на этот случай.

  • Проблема выглядит примерно так: Java VM: воспроизводимый SIGSEGV на 1.6.0_17 и 1.6.0_18, каксообщить? но я не могу это подтвердить, так как *Файл 1038 * отсутствует и, конечно, платформа ОС отличается.
  • (РЕДАКТИРОВАТЬ) Как предлагается в одном из ответов на Инструмент для анализа дампа ядра Java вопросЯ извлек дамп кучи из файла core, используя jmap, и проанализировал его с помощью Eclipse MAT.Я обнаружил утечку (элементы, добавленные в HashMap, никогда не подлежат очистке, во время разгрузки ядра 1,4 млн элементов).Это, однако, не объясняет, почему файл hs_err_pid.log не был сгенерирован, а также сбой jvm.
  • (EDIT2) В соответствии с предложением Darryl Miles, были проверены ограничения -Xmx (тест содержал код, который неограниченно добавляет объекты в LinkedList):
    • java -Xmx1444m Test результаты с java.lang.OutOfMemoryError: Java heap space,
    • java -Xmx2048m Test результаты с java.lang.OutOfMemoryError: Java heap space,
    • java -Xmx3600m Test результаты с дампом ядра.

Вопрос

Кто-нибудь сталкивался с подобной проблемой с jvm и как действовать в таких случаях, чтобы выяснить, что на самом деле произошло (т.е. в каком случае ядро ​​выгружается из jvm и нет hs_err_pid.log файл создан)?

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

Извлеченные флаги

# pflags core
...
/2139095:      flags = DETACH
    sigmask = 0xfffffeff,0x0000ffff  cursig = SIGSEGV

Извлеченный стек

# pstack core
...
-----------------  lwp# 2139095 / thread# 2139095  --------------------
 fb208c3e ???????? (f25daee0, f25daec8, 74233960, 776e3caa, 74233998, 776e64f0)
 fb20308d ???????? (0, 1, f25db030, f25daee0, f25daec8, 7423399c)
 fb20308d ???????? (0, 0, 50, f25da798, f25daec8, f25daec8)
 fb20308d ???????? (0, 0, 50, f25da798, 8561cbb8, f25da988)
 fb203403 ???????? (f25da988, 74233a48, 787edef5, 74233a74, 787ee8a0, 0)
 fb20308d ???????? (0, f25da988, 74233a78, 76e2facf, 74233aa0, 76e78f70)
 fb203569 ???????? (f25da9b0, 8b5b400, 8975278, 1f80, fecd6000, 1)
 fb200347 ???????? (74233af0, 74233d48, a, 76e2fae0, fb208f60, 74233c58)
 fe6f4b0b __1cJJavaCallsLcall_helper6FpnJJavaValue_pnMmethodHandle_pnRJavaCallArguments_pnGThread__v_ (74233d44, 74233bc8, 74233c54, 8b5b400) + 1a3
 fe6f4db3 __1cCosUos_exception_wrapper6FpFpnJJavaValue_pnMmethodHandle_pnRJavaCallArguments_pnGThread__v2468_v_ (fe6f4968, 74233d44, 74233bc8, 74233c54, 8b5b4
00) + 27
 fe6f4deb __1cJJavaCallsEcall6FpnJJavaValue_nMmethodHandle_pnRJavaCallArguments_pnGThread__v_ (74233d44, 8975278, 74233c54, 8b5b400) + 2f
 fe76826d __1cJJavaCallsMcall_virtual6FpnJJavaValue_nLKlassHandle_nMsymbolHandle_4pnRJavaCallArguments_pnGThread__v_ (74233d44, 897526c, fed2d464, fed2d6d0, 7
4233c54, 8b5b400) + c1
 fe76f4fa __1cJJavaCallsMcall_virtual6FpnJJavaValue_nGHandle_nLKlassHandle_nMsymbolHandle_5pnGThread__v_ (74233d44, 8975268, 897526c, fed2d464, fed2d6d0, 8b5b
400) + 7e
 fe7805f6 __1cMthread_entry6FpnKJavaThread_pnGThread__v_ (8b5b400, 8b5b400) + d2
 fe77cbe4 __1cKJavaThreadRthread_main_inner6M_v_ (8b5b400) + 4c
 fe77cb8e __1cKJavaThreadDrun6M_v_ (8b5b400) + 182
 feadbd59 java_start (8b5b400) + f9
 feed59a9 _thr_setup (745c5200) + 4e
 feed5c90 _lwp_start (745c5200, 0, 0, 74233ff8, feed5c90, 745c5200)

Системная информация:

# uname -a
SunOS xxxx 5.10 Generic_137138-09 i86pc i386 i86pc
# java -version
java version "1.6.0_11"
Java(TM) SE Runtime Environment (build 1.6.0_11-b03)
Java HotSpot(TM) Server VM (build 11.0-b16, mixed mode)
# ulimit -a
time(seconds) unlimited
file(blocks) unlimited
data(kbytes) unlimited
stack(kbytes) 10240
coredump(blocks) unlimited
nofiles(descriptors) 256
memory(kbytes) unlimited

Использованные аргументы jvm:

java -Xms1024M -Xmx2048M -verbose:gc -Xloggc:logs/gc.log -server com.example.MyApplication

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

Ответы [ 2 ]

3 голосов
/ 08 октября 2011

Согласно моим комментариям выше. Я считаю, что эта проблема исчерпывает полезную кучу в 32-битном адресном пространстве, установив слишком высокое значение -Xmx. Это заставило Ядро контролировать ограничение (отказывая в запросах на новую память), прежде чем JVM сможет его контролировать (используя контролируемый механизм OutOfMemoryException). К сожалению, я не знаю особенностей Intel Solaris, чтобы знать, чего ожидать от этой платформы.

Но, как правило, для Windows максимальный -Xmx может быть 1800M, а затем уменьшить его на 16M для каждого создаваемого вами потока приложения. Поскольку каждому потоку требуется пространство стека (как нативного, так и стека Java), а также другие вопросы учета для каждого потока, такие как локальное хранилище потоков и т. Д. Результат этих вычислений должен дать вам приблизительное значение реалистичного используемого пространства кучи виртуальной машины Java на любом 32-битном процессе, операционная система которого использует разделение 2G / 2G (пользователь / ядро).

В WinXP и выше можно использовать переключатель / 3G на ядре для получения более высокого разделения (пользователь / ядро ​​3G / 1G), а в Linux имеется файл / proc / / map, позволяющий вам точно увидеть, как адресное пространство процесса составлено из данного процесса (если бы вы запускали это приложение, вы могли бы со временем наблюдать, как увеличивается [куча], чтобы соответствовать сопоставлениям общих файлов, используемых для .text / .rodata / .data / etc ... из DSO это приводит к тому, что ядро ​​отклоняет запросы на увеличение кучи.

Эта проблема решена для 64-битной системы, поскольку здесь гораздо больше адресного пространства, и вам не хватит физической и виртуальной (подкачки) памяти до того, как куча встретит другие сопоставления.

Я полагаю, что 'truss' в Solaris обнаружил бы системный вызов brk / sbrk, который возвратил код ошибки, незадолго до дампа ядра. Части стандартных собственных библиотек кодируются так, чтобы никогда не проверять код возврата из запросов на новую память, и в результате можно ожидать сбои.

3 голосов
/ 05 октября 2011

6.0_11 довольно старый, и у меня нет опыта в последнее время, очень рекомендую обновить его там ...

Однако, не может произойти аварийный дамп со стеком в нативном коде, то есть вызов некоторой нативной функции (напримерзапись FileOutputStream, сокеты используют тот же Impl) с очень низким стеком.Таким образом, даже несмотря на то, что JVM пытается записать файл, недостаточно стека и код записи также дает сбой.Второй стекопоток просто спасает процесс.

У меня был похожий случай (файл не создан) в производственной системе, и было нелегко отследить его, но выше объясняет причину.

...