Minecraft Руководство

Сервер Minecraft падает из-за памяти: ошибка Java или OOM kill?

Различите нехватку heap Java, native-памяти и OOM kill Linux или контейнера, прежде чем менять объём RAM для Minecraft.

Сервер Minecraft падает из-за памяти: ошибка Java или OOM kill?

Прежде чем увеличивать RAM для Minecraft, выясните, что завершило процесс. Переполнение heap Java, нехватка native-памяти и OOM kill Linux требуют разных проверок. Увеличение -Xmx может усугубить нехватку памяти хоста или контейнера.

Разбираем существующий сервер Paper на Ubuntu 24.04 с SSH и sudo. Примеры используют minecraft.service и /srv/minecraft из инструкции по установке. Замените их своими именами. Для контейнера дополнительно проверьте лимиты через управляющую им систему: вся RAM VPS не обязательно доступна этому серверу.

Сохраните данные до остановки цикла перезапусков#

Запишите время сбоя, действия игроков и последнее изменение. Сохраните журнал службы вместе с журналом ядра: короткий фрагмент latest.log может не содержать исходную причину. На VPS создайте каталог, доступный только вашему пользователю:

bash
(
set -e
umask 077
MC_EVIDENCE="$HOME/minecraft-memory-$(date +%F-%H%M%S)"
mkdir "$MC_EVIDENCE"
sudo journalctl -u minecraft --since '30 minutes ago' --no-pager > "$MC_EVIDENCE/service.log"
sudo journalctl -k --since '30 minutes ago' --no-pager > "$MC_EVIDENCE/kernel.log"
sudo systemctl show minecraft -p Result -p NRestarts -p ExecMainCode -p ExecMainStatus -p ExecStart > "$MC_EVIDENCE/service-state.txt"
)

Также сохраните относящийся к сбою crash report игры, если он появился. Перед сбором больших файлов проверьте свободное место. Если служба постоянно запускается и падает, после сохранения данных остановите её:

bash
sudo systemctl stop minecraft
sudo journalctl -u minecraft -n 60 --no-pager

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

Разберите конкретное сообщение#

Руководство Oracle по памяти различает исчерпанные области JVM. Сохраняйте уточнение после OutOfMemoryError: не каждое такое исключение означает маленький heap.

ДанныеЧто из них следуетСледующая проверка
OutOfMemoryError: Java heap spaceНе удалось выделить память в heapРазмер heap, живые объекты и нагрузка в момент сбоя
OutOfMemoryError: MetaspaceИсчерпана память метаданных классовЗагрузка классов, плагины и явный лимит Metaspace
Сбой native allocation или unable to create native threadНе удалось выделить внеheap-память либо создать потокNative-память, число потоков и ограничения процесса
Запись OOM ядра называет PID JavaLinux убил этот процесс при нехватке памятиОграничение хоста или memory cgroup в той же записи
Только SIGKILL, Killed или код 137Процесс завершён принудительноДанные ядра, службы и провайдера или контейнера; причина пока неизвестна

Сигнал kill может отправить администратор, supervisor или служба после превышения времени остановки. Журнал ядра может быть недоступен или уже ротирован. Его отсутствие не доказывает, что памяти хватало; необъяснённое завершение не доказывает OOM. Watchdog и UnsupportedClassVersionError требуют других проверок; для последнего есть инструкция по версии Java.

Исключение указывает на область памяти JVM, а запись OOM ядра — на предел хоста или cgroup. Одного кода 137 для вывода недостаточно.

Сравните heap, процесс и весь хост#

-Xmx ограничивает heap Java, а не весь процесс. Стеки JVM, метаданные классов и другие native-выделения находятся за его пределами. Память нужна Linux, файловому кешу и остальным службам. Проверьте параметры в реальном ExecStart или обёртке: процентные настройки и аргументы, сформированные панелью, могут отличаться от ожидаемого объёма.

Во время контролируемого наблюдения за работающим сервером выполните:

bash
free -h
vmstat 1 10
sudo systemctl show minecraft -p MainPID -p MemoryCurrent -p MemoryHigh -p MemoryMax
MC_PID="$(systemctl show minecraft -p MainPID --value)"
if [ "$MC_PID" -gt 0 ]; then
  sudo ps -p "$MC_PID" -o pid,rss,vsz,args
fi

По справочнику free, available оценивает память, доступную без подкачки; низкое значение free отдельно не означает нехватку. vmstat показывает вход и выход страниц swap как si и so. Сопоставляйте со сбоем последующие строки: первая усредняет данные с загрузки системы. Постоянная активность — повод исследовать давление на память, а не отключать swap по чужому рецепту.

Справочник ps различает RSS, резидентную память процесса, и VSZ, виртуальное адресное пространство. Ни одно значение не равно живому heap Java. Если основной PID принадлежит shell-обёртке, найдите Java через systemctl status и проверьте её процесс. Сравнивайте похожую активность игроков: показания пустого сервера после перезапуска не объясняют пик перед падением.

Проверьте границу памяти службы#

На хосте может оставаться доступная RAM, хотя ограниченная служба или контейнер уже упирается в свой предел. Настройки ресурсов systemd разделяют порог давления MemoryHigh и жёсткий предел MemoryMax. Родительский slice может ограничивать память сильнее, даже если у самой службы указано infinity.

Для работающей обычной systemd-службы на хосте с cgroup v2:

bash
MC_CGROUP="$(systemctl show minecraft -p ControlGroup --value)"
if [ -n "$MC_CGROUP" ] && [ "$MC_CGROUP" != '/' ]; then
  for MC_FILE in memory.current memory.max memory.events; do
    MC_PATH="/sys/fs/cgroup$MC_CGROUP/$MC_FILE"
    if [ -r "$MC_PATH" ]; then
      printf '%s\n' "$MC_PATH"
      cat "$MC_PATH"
    fi
  done
fi

Документация ядра определяет эти файлы: объёмы указаны в байтах, max означает отсутствие локального предела, а счётчики событий накопительные. Сравнивайте их до и после контролируемого сбоя. oom_kill учитывает OOM-жертвы в этой cgroup, в том числе при глобальном OOM; сам по себе счётчик не объясняет, какое ограничение стало причиной. Сопоставьте его с записью ядра и унаследованными лимитами. После пересоздания cgroup старые счётчики могут исчезнуть.

Если файлов нет, это не подтверждает отсутствие ограничений. Служба может быть остановлена, использовать другую иерархию или работать внутри пространства имён контейнера. Проверьте родительские cgroup и квоты контейнера или провайдера через управляющего ими администратора. Не удаляйте квоту, которая одновременно защищает остальные службы VPS.

Соберите данные JVM при повторяемой нагрузке#

Если сервер способен безопасно работать, используйте аккаунт оператора с необходимыми правами spark. В чате Minecraft:

text
/spark gc
/spark gcmonitor

Справочник spark описывает историю GC и переключатель мониторинга. Запишите действия игроков и время; после наблюдения снова выполните /spark gcmonitor, чтобы выключить монитор. Для постоянных лагов или долгих тиков используйте отдельную инструкцию по профилированию spark.

При контролируемом запуске с Java 21/25 журнал GC позволяет сохранить данные после перезапуска. Добавьте -Xlog:gc*:file=logs/gc.log:time,uptime,level,tags:filecount=5,filesize=10M перед -jar в текущую команду, сохранив исполняемый файл и остальные аргументы. Проверьте, что /srv/minecraft/logs существует и пользователь службы может туда писать. До перезапуска скопируйте прежние журналы GC: ротация может заменить старые данные. Синтаксис ротации и параметры heap описаны в справочнике команды Java.

Растущий график занятой памяти отдельно не доказывает утечку. Ищите рост живых объектов после сборок мусора при сопоставимой устойчивой нагрузке. Если он продолжается, проверяйте подозреваемый плагин на сохранённой копии или передайте данные его разработчику. Heap dump может приостановить JVM и занять много места: собирайте его с понятным планом анализа и достаточным свободным диском, ограничивая доступ к содержимому.

Выберите одно изменение и повторите наблюдение#

Если исключение относится к heap и есть реальный запас на хосте и в квоте, проверьте обоснованное увеличение heap либо уменьшите нагрузку, удерживающую данные. При OOM хоста или cgroup уменьшите суммарный бюджет, перенесите конкурирующие службы или согласуйте дополнительную ёмкость. Heap размером со всю машину или лимит контейнера не оставляет места для накладных расходов. Heap 2 GiB на VPS с 4 GiB из нашей инструкции — пример распределения, а не гарантия вместимости сервера.

Сбои Metaspace и потоков требуют собственных данных: изменение -Xmx напрямую их не исправляет. Ограничения создания потоков Linux могут мешать новому потоку, даже если в heap есть место. Регулярный перезапуск может временно скрывать накопление, одновременно уничтожая полезный тренд. Сохраните исходную конфигурацию, измените один параметр и сравните следующую похожую сессию по пикам памяти и журналам, а не только по времени работы.

Для поддерживаемых экземпляров на собственном VPS мониторинг серверов в Nexardo упрощает регулярное наблюдение за ресурсами. Он сам по себе не определяет причину OOM и не подключает автоматически эту ручную службу.

После исправления перечитайте изменённый unit через sudo systemctl daemon-reload. Если systemd достиг лимита частоты запусков, выполните sudo systemctl reset-failed minecraft, затем в период обслуживания запустите службу командой sudo systemctl start minecraft. Проверьте готовность игры и подключитесь клиентом. Успешный перезапуск — начало проверки: повторите прежнюю нагрузку и убедитесь, что тот же сбой памяти больше не возникает.