Неожиданная остановка JVM-процесса (Linux)
При работе на enterprise-сервере под управлением Linux и большой JVM (десятки гигабайт heap, DirectMemory, ZGC и т.д.) процесс может неожиданно завершаться. Причины могут быть как в самой JVM, так и во внешней среде (ядро, мониторинг, лимиты). Ниже объединены рекомендации по диагностике и предотвращению таких падений.
1. Проверить логи ядра (dmesg
и /var/log/kern.log
)
Частая причина — OOM Killer или аппаратные/системные ошибки.
Пример вывода при нехватке памяти:
2. Проверить системные логи (/var/log/syslog
, journalctl
)
3. Проверить, был ли процесс убит OOM Killer
4. Проверить ограничения (ulimit
, cgroups, systemd`)
ulimit
:ulimit -acgroups:
systemd-cgtopsystemd:
systemctl status archiva.service journalctl -u archiva.service -xe
Если OOMKilled=yes
→ ядро или systemd принудительно завершили процесс.
5. Проверить сигналы и трассировку
Если процесс падает по
SIGSEGV
,SIGBUS
илиSIGILL
, в каталоге будетhs_err_pid*.log
.Для живого процесса:
strace -p PIDДля запуска с нуля:
strace ./startup.sh
6. Проверить внешнее завершение (мониторинг, supervisor, cron)
Использовать
pstree
для иерархии процессов.Проверить
auditd
, если есть подозрение на внешние kill-сигналы.
7. Проверить использование памяти и CPU
Если
si/so
(swap in/out) активно растут → JVM страдает от свопа.Если Java в
smem
занимает десятки гигабайт swap → heap выгружен ядром.
8. Проверить SELinux / AppArmor
9. Специфика JVM (enterprise-сценарий)
Основные риски
OOM Killer ядра: когда JVM (heap + DirectMemory + native + metaspace) превысила RAM + swap.
GC завис из-за swap: страницы heap в swap → ZGC/GC начинают работать с диском, приложение подвисает → мониторинг/systemd убивает процесс.
Что делать
Понизить swappiness:
sysctl -w vm.swappiness=1 echo 'vm.swappiness=1' >> /etc/sysctl.conf→ снизит вероятность выгрузки heap в swap.
Включить GC-логи:
-Xlog:gc*,gc+cpu=debug,gc+heap=debug:file=/var/opt/mailarchiva/logs/gc.log:time,uptime,level,tags→ анализировать ZGC-паузы и нагрузку.
Следить за native memory: Добавить:
-XX:NativeMemoryTracking=summary -XX:+UnlockDiagnosticVMOptions -XX:+PrintNMTStatistics→ при остановке JVM будет видно, куда ушла native-память.
Проверять OOM Killer:
dmesg | grep -i kill journalctl -k | grep -i killУточнить лимиты systemd:
MemoryMax=
,LimitNOFILE=
и пр. в unit-файле сервиса.При ограничениях контейнера (Docker/K8s) проверить
--memory
и--memory-swap
.
Выводы
Если процесс убит OOM Killer → уменьшить heap/DirectMemory, увеличить RAM или снизить
swappiness
.Если процесс падает с
SIGSEGV
и естьhs_err_pid
→ отладка JNI/библиотек, проверить JDK.Если процесс зависает из-за swap → ограничить swap, оптимизировать GC и настройки памяти.
Если проблема в лимитах (
ulimit
,cgroups
) → увеличить лимиты или изменить unit-файл.Если виноват мониторинг/systemd watchdog → проверить настройки health-check.
Таким образом, диагностика падения JVM сводится к анализу логов ядра, системных логов, ограничений окружения и GC-логов. Для enterprise-нагрузки критично минимизировать работу со swap и контролировать распределение памяти между heap, DirectMemory и native-кодом.