SystemdDoctor
служба не работает java память

Java-служба: OutOfMemoryError и куча

У служб на JVM две границы памяти: размер кучи в настройках JVM и предел контрольной группы в unit-файле. Нехватка первой даёт ошибку внутри приложения, превышение второй — убийство процесса ядром.

Вероятные причины

По порядку: сверху то, что встречается чаще.

  1. Куче не хватает памяти

    Приложение выбрасывает ошибку нехватки памяти и может продолжать работать в неработоспособном состоянии. Это хуже падения: служба «активна», а запросы не обрабатываются.

  2. Предел контрольной группы ниже потребности JVM

    JVM расходует память и вне кучи: метаданные, стеки потоков, буферы. Предел должен быть больше кучи с запасом.

  3. Дамп кучи не сохраняется, и причина неизвестна

    Без дампа непонятно, что заняло память. Разбор превращается в догадки.

Диагностика

Команды идут в том порядке, в котором их стоит выполнять: каждая следующая проверяет то, что осталось после предыдущей.

Ошибки нехватки памяти в журнале.

journalctl -u myapp.service -n 60 --no-pager | grep -iE "OutOfMemory|GC overhead"

Предел и пиковое потребление службы.

systemctl show myapp.service -p MemoryMax -p MemoryPeak

Убивало ли процесс ядро.

journalctl -k -b --no-pager | grep -i "killed process" | grep -i java

Решение

Решение своё для каждой причины. Сначала определите, какая из них ваша, — иначе правки наложатся друг на друга.

1. Куче не хватает памяти
Почему происходит
Приложение выбрасывает ошибку нехватки памяти и может продолжать работать в неработоспособном состоянии. Это хуже падения: служба «активна», а запросы не обрабатываются.
Как проверить
Посмотрите журнал и размер кучи.
journalctl -u myapp.service -n 40 --no-pager | grep -i "OutOfMemoryError"
systemctl cat myapp.service | grep -iE "Xmx|Xms"
Как исправить
Увеличьте кучу или уменьшите потребление. Добавьте ключ, завершающий процесс при нехватке памяти: тогда systemd перезапустит службу вместо работы в сломанном виде.
# в ExecStart: -XX:+ExitOnOutOfMemoryError
2. Предел контрольной группы ниже потребности JVM
Почему происходит
JVM расходует память и вне кучи: метаданные, стеки потоков, буферы. Предел должен быть больше кучи с запасом.
Как проверить
Сравните предел и размер кучи.
systemctl show myapp.service -p MemoryMax -p MemoryPeak
systemctl cat myapp.service | grep -i Xmx
Как исправить
Задайте предел службы с запасом примерно в треть от размера кучи, либо укажите JVM долю памяти контейнера вместо абсолютного размера.
3. Дамп кучи не сохраняется, и причина неизвестна
Почему происходит
Без дампа непонятно, что заняло память. Разбор превращается в догадки.
Как проверить
Посмотрите, включено ли сохранение дампа.
systemctl cat myapp.service | grep -i HeapDump
Как исправить
Включите сохранение дампа кучи при нехватке памяти в каталог службы: файл пригодится для разбора.
# -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/var/lib/myapp

Пример вывода

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

myapp[1200]: Exception in thread "http-worker-12" java.lang.OutOfMemoryError: Java heap space
myapp[1200]: java.lang.OutOfMemoryError: GC overhead limit exceeded
# служба при этом остаётся active (running)

Связанные ошибки

Где встречается чаще всего

Источники

  • Документация JVM: параметры памяти документация программы
    сверено 15 сентября 2026
  • Воспроизведено на тестовой машине, systemd 255 (Ubuntu 24.04)
    Воспроизведено приложением на JVM с кучей больше предела контрольной группы.
    собственная проверка, systemd 255
    сверено 15 сентября 2026