Полезен ли corefile Java, созданный с помощью gcore?

У нас есть приложение JAVA, которое вызывает сбой нашего сервера redhat (30 ядер / 512 ГБ оперативной памяти), потребляя некоторый (неизвестный?) Ресурс, не позволяющий другим компонентам создавать новые потоки, в настоящее время мы работаем над этим, убивая процесс, который рассылает спам потоки Каждый раз, когда возникает проблема, и это происходит примерно каждые 15 дней, мы пытались установить огромные значения в /etc/security/limits.conf, но мы решаем проблему еще до достижения этого предела.

В прошлый раз я подсчитал количество потоков с помощью ps -efL | wc -l, 10000 потоков много для нашего зверя, зная, что потребление CPU/RAM было низким в тот момент? Я использовал gstack, чтобы попытаться выяснить, где он застрял, но поскольку это idk программы JAVA, имеет ли вывод значимый? но я смог определить закономерность: большинство из 9000 потоков выглядят так:

Thread 9049 (Thread 0x7f43d5087700 (LWP 123925)):
#0  0x00007f43d791e705 in pthread_cond_wait@@GLIBC_2.3.2 () from /lib64/libpthread.so.0
#1  0x00007f43d6a94f33 in os::PlatformEvent::park() () from /opt/3pp/jdk1.8.0_25/jre/lib/amd64/server/libjvm.so
#2  0x00007f43d6a58e67 in Monitor::IWait(Thread*, long) () from /opt/3pp/jdk1.8.0_25/jre/lib/amd64/server/libjvm.so
#3  0x00007f43d6a59786 in Monitor::wait(bool, long, bool) () from /opt/3pp/jdk1.8.0_25/jre/lib/amd64/server/libjvm.so
#4  0x00007f43d6c48e1b in GangWorker::loop() () from /opt/3pp/jdk1.8.0_25/jre/lib/amd64/server/libjvm.so
#5  0x00007f43d6a9bd48 in java_start(Thread*) () from /opt/3pp/jdk1.8.0_25/jre/lib/amd64/server/libjvm.so
#6  0x00007f43d791adf5 in start_thread () from /lib64/libpthread.so.0
#7  0x00007f43d722f1ad in clone () from /lib64/libc.so.6
Thread 9048 (Thread 0x7f43d4f86700 (LWP 123926)):
#0  0x00007f43d791e705 in pthread_cond_wait@@GLIBC_2.3.2 () from /lib64/libpthread.so.0
#1  0x00007f43d6a94f33 in os::PlatformEvent::park() () from /opt/3pp/jdk1.8.0_25/jre/lib/amd64/server/libjvm.so
#2  0x00007f43d6a58e67 in Monitor::IWait(Thread*, long) () from /opt/3pp/jdk1.8.0_25/jre/lib/amd64/server/libjvm.so
#3  0x00007f43d6a59786 in Monitor::wait(bool, long, bool) () from /opt/3pp/jdk1.8.0_25/jre/lib/amd64/server/libjvm.so
#4  0x00007f43d6c48e1b in GangWorker::loop() () from /opt/3pp/jdk1.8.0_25/jre/lib/amd64/server/libjvm.so
#5  0x00007f43d6a9bd48 in java_start(Thread*) () from /opt/3pp/jdk1.8.0_25/jre/lib/amd64/server/libjvm.so
#6  0x00007f43d791adf5 in start_thread () from /lib64/libpthread.so.0
#7  0x00007f43d722f1ad in clone () from /lib64/libc.so.6

Также перед тем, как убить процесс, я использовал gcore -o /tmp/dump.txt, это правильный способ получить corefile процесса java?

Когда я пытаюсь взглянуть с помощью gdb, я не получаю отладочных символов и не дамп ядра. Правильный ли это способ проверить такие файлы?

M1:~# gdb /opt/3pp/jre/bin/java /tmp/dump.txt.123913 
GNU gdb (GDB) 
Copyright (C) 2013 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-redhat-linux-gnu".
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>...
Reading symbols from /opt/3pp/jre/bin/java...(no debugging symbols 
"/tmp/dump.txt.123913" is not a core dump: File format not recognized
Missing separate debuginfos, use: debuginfo-install jre1.8.0_25-1.8.0_25-fcs.x86_64

Спасибо заранее за ваше время.

2 ответа

В прошлый раз я подсчитал количество потоков, используя ps -efL | wc -l, 10000 потоков много для нашего зверя, зная, что потребление CPU/RAM было низким в тот момент?

Ни это не незначительное число потоков, но нет, 10K нити не что много, особенно для 30 ядра машины. 4-ядерный рабочий стол Windows, на котором я сейчас работаю, имеет ~3K.

Я использовал gstack, чтобы попытаться выяснить, где он застрял, но поскольку это idk программы JAVA, имеет ли вывод значимый?

Я никогда не пробовал отлаживать Java, используя собственные стеки потоков, но эта трассировка стека для меня выглядит как "припаркованный" поток. Другими словами, поток в некотором пуле потоков, которому нечего делать, ожидает своей работы. См. Этот ответ для получения более подробной информации.

Также перед тем, как убить процесс, я использовал gcore -o /tmp/dump.txt, это правильный способ получить файл ядра Java-процесса?

Вероятно, это имеет некоторую ценность, но я бы предложил использовать для этой работы инструменты, специфичные для java. Первое, что приходит в голову, этоjcmdкоторый поставляется с JDK. Вот ссылка для начала. Версия Java 9 имеет более приятную документацию и очень похожа.

Я бы специально использовал Thread.print команда jcmd для печати трассировки стека на уровне Java и GC.heap_dump сбросить всю кучу java в .hprofфайл, который впоследствии можно будет проанализировать с помощью таких инструментов, как MAT.

Если вы используете JDK 8 с "Коммерческими функциями", вы также можете включить JFR (Java Flight Recorder, который отслеживает выполнение процесса. Файлы, созданные JFR, могут быть открыты либо с помощью Oracle "Mission Control", либо альтернативный "Центр управления полетами", такой как тот, что у Азула, называется Зулу.

Наконец, вы также можете попытаться подключиться к процессу с помощью jconsole, еще одного инструмента, поставляемого с JDK.

Удачи.

Я дам вам общий совет относительно файлов ядра JVM, чтобы вы могли выбрать, копаться в них или нет.

Полезен ли corefile Java, созданный с помощью gcore?

Это действительно полезно, но если вы не знаете о конкретной реализации JVM, это будет выглядеть беспорядочно. Трассировки стека в полном порядке, и сбой определенно не произошел из-за вызоваpthread_cond_wait (если сам pthread не содержит ошибок, что крайне маловероятно).

У нас есть приложение JAVA, которое дает сбой

Вы запускали тест памяти? Реализация JVM HotSpot очень надежна в подавляющем большинстве случаев.

это правильный способ получить файл ядра Java-процесса?

Вы также можете использовать generate-core-file в GDB

нет отладочных символов

Вы уже показали трассировки стека с отладочными символами. Возможно что-то не так с основным файлом. Пытатьсяgdb generate-core-file

Если вы хотите покопаться в дампе ядра HotSpot, я могу посоветовать следующую последовательность действий:

  1. info threads чтобы найти "аварийную ветку"
  2. Перейти к этой теме с thread N где N это номер "аварийного потока"
  3. disas чтобы разобрать функцию и узнать инструкцию, вызвавшую сбой
  4. В случае, если это просто произошло из-за разыменования указателя мусора, переверните его, чтобы выяснить, откуда взялось значение

Все усложняется, если вы разбились с чем-то вроде Bus Error из-за неправильного mmapиспользование или около того. Все становится еще сложнее, если вы разбились в JIT-скомпилированном методе, поэтомуbt, disasа друзья не пригодятся. Возможный путь - сбросить скомпилированный код из nmethod с помощью code_offset и попытаться выяснить, что пошло не так.

Другие вопросы по тегам