Как исправить ошибку Out of Memory

1. Диагностика источника ошибки

Прежде чем увеличивать память, определите, где именно происходит сбой: в JVM (Java Heap) или на уровне ОС (OOM Killer).

1.1 Проверка логов сервера Minecraft

Подключитесь по SSH к вашему выделенному серверу на Ubuntu и проверьте последние строки лога:

tail -n 100 /var/log/minecraft/latest.log

Ищите строки:

  • java.lang.OutOfMemoryError: Java heap space — не хватает кучи (Heap) внутри JVM.
  • java.lang.OutOfMemoryError: Metaspace — не хватает памяти под метаданные классов.
  • Killed в системном логе (см. пункт 1.2) — процесс убит OOM Killer'ом Linux.

1.2 Проверка системного лога (OOM Killer)

Выполните команду:

grep -i "out of memory" /var/log/syslog

Если есть записи Out of memory: Kill process <PID> (java), значит, хост-система (Ubuntu на Proxmox) убивает процесс, так как сумма RSS памяти превышает лимит контейнера/ВМ или физической RAM.

Важно для proxify.cloud: В панели proxify.cloud перейдите в раздел «Серверы» → выберите ваш выделенный сервер → вкладка «Ресурсы». Посмотрите график «Memory Usage». Если пик совпадает с крашем — проблема в лимите тарифа или утечке на уровне ОС.

2. Настройка JVM-аргументов (Java Heap)

Самая частая причина — некорректные флаги -Xms и -Xmx в скрипте запуска.

2.1 Определение доступной памяти

Узнайте сколько RAM выделено контейнеру/ВМ:

free -h

Пример вывода: Mem: 15G. Оставьте 1.5–2 ГБ под ОС, буферы кэша диска и off-heap память Java (Metaspace, CodeCache, Direct Memory, Thread Stacks). Для 16 ГБ тарифа на proxify.cloud безопасный Heap: 13–14 ГБ.

2.2 Редактирование стартового скрипта

Обычно скрипт находится в /home/minecraft/start.sh или /opt/minecraft/start.sh. Откройте его:

nano /home/minecraft/start.sh

Неправильный пример:

java -Xmx16G -Xms16G -jar paper.jar

(Запрашивает больше, чем есть физически).

Правильный пример для 16 ГБ RAM (Heap 13 ГБ):

#!/bin/bash
cd /home/minecraft/server

JAVA_OPTS="
-Xms13G
-Xmx13G
-XX:+UseG1GC
-XX:+ParallelRefProcEnabled
-XX:MaxGCPauseMillis=200
-XX:+UnlockExperimentalVMOptions
-XX:+DisableExplicitGC
-XX:+AlwaysPreTouch
-XX:G1NewSizePercent=30
-XX:G1MaxNewSizePercent=40
-XX:G1HeapRegionSize=8M
-XX:G1ReservePercent=20
-XX:InitiatingHeapOccupancyPercent=15
-Dterminal.jline=false
-Dterminal.ansi=true
"

java $JAVA_OPTS -jar paper-1.20.4.jar nogui
  • -Xms = -Xmx — предотвращает расширение кучи во время игры (лаги).
  • -XX:+AlwaysPreTouch — затрагивает страницы памяти при старте, снижает задержки при первом аллоцировании.
  • G1GC флаги — оптимизированы для больших куч (>6 ГБ) и низкой задержки.

Сохраните (Ctrl+O, Enter) и выйдите (Ctrl+X). Сделайте исполняемым:

chmod +x /home/minecraft/start.sh

2.3 Если используется systemd-юнит

Проверьте /etc/systemd/system/minecraft.service:

[Service]
WorkingDirectory=/home/minecraft/server
ExecStart=/home/minecraft/start.sh
MemoryLimit=15G       # Жесткий лимит cgroups (не выше тарифа proxify.cloud)
MemorySwapMax=0       # Отключаем своп для Java-процесса

После изменений:

systemctl daemon-reload
systemctl restart minecraft

3. Оптимизация конфигурации сервера (Paper/Spigot/Purpur)

Некорректные настройки paper-global.yml, bukkit.yml, spigot.yml заставляют сервер держать в памяти лишние чанки и энтити.

3.1 paper-global.yml (Ключевые параметры)

Путь: /home/minecraft/server/paper-global.yml

chunk-loading:
  # Уменьшаем окно активных чанков вокруг игрока
  player-chunk-load-radius: 6  # дефолт 10, 6-7 достаточно для геймплея

entity-tracking:
  # Реже шлем пакеты для далеко находящихся мобов
  players:
    tracking-range: 48
  animals:
    tracking-range: 48
  monsters:
    tracking-range: 48

# Ограничение тиков сущностей, если сервер отстает
max-entity-collisions: 2

3.2 bukkit.yml (Спавн и чанки)

Путь: /home/minecraft/server/bukkit.yml

spawn-limits:
  monsters: 50        # дефолт 70
  animals: 15         # дефолт 15
  water-animals: 5    # дефолт 5
  ambient: 10         # дефолт 15
chunk-gc:
  period-in-ticks: 400  # дефолт 600, чаще чистим неиспользуемые чанки

3.3 spigot.yml (Сохранение и активация)

Путь: /home/minecraft/server/spigot.yml

save-user-cache-on-stop-only: true  # Не пишем usercache.json каждую минуту
entity-activation-range:
  animals: 16
  monsters: 24
  raiders: 48
  misc: 8
  water: 8
  villagers: 16
  flying-monsters: 48

Примените изменения: полный рестарт сервера (systemctl restart minecraft или через скрипт). Релоад (/reload) не сработает для большинства параметров.

4. Работа с Off-Heap памятью и Metaspace

Если в логах OutOfMemoryError: Metaspace или Direct buffer memory, Heap настройки не помогут.

4.1 Ограничение Metaspace

Добавьте в JAVA_OPTSstart.sh):

-XX:MaxMetaspaceSize=512M

512 МБ достаточно для большинства модпаков/плагинов. Не ставьте неограниченно.

4.2 Ограничение Direct Memory (NIO buffers)

Paper/Netty используют Direct Memory для сетевых буферов. Лимит по умолчанию равен -Xmx. Явно ограничьте:

-XX:MaxDirectMemorySize=1G

Добавьте в JAVA_OPTS перед -jar.

4.3 Размер стека потоков

Много плагинов = много потоков. Уменьшите стек с дефолтных 1МБ до 512КБ:

-Xss512k

Экономит сотни мегабайт при 200+ потоках.

5. Настройка Swap и OOM Score (Уровень ОС Ubuntu)

На выделенных серверах proxify.cloud своп часто отключен или мал. Java не любит своп (GC ломается), но отсутствие свопа гарантирует OOM Kill при утечке.

5.1 Создание ZRAM swap (рекомендуется для Ubuntu 22.04+)

ZRAM сжимает страницы в RAM, давая "воздух" перед OOM Kill без сильных лагов на диске.

apt update && apt install -y zram-config

Отредактируйте /etc/default/zramswap:

# Процент от RAM (например, 25% от 16ГБ = 4ГБ сжатого свопа)
PERCENT=25
# Приоритет
PRIORITY=100

Перезапустите:

systemctl restart zramswap
swapon --show

5.2 Защита процесса от OOM Killer

Снизьте oom_score_adj для Java-процесса, чтобы ядро убивало другие процессы (bash, ssh, monitoring) в первую очередь.

В start.sh перед запуском java добавьте:

# Получаем PID текущего шелла (который станет родителем java) и понижаем приоритет
echo -100 > /proc/self/oom_score_adj

Или, если используете systemd, в [Service] юнита:

OOMScoreAdjust=-100

6. Мониторинг и профилирование в продакшене

Не гадайте — собирайте метрики.

6.1 Встроенный Timings (Paper/Purpur)

В игре или консоли:

/timings on
# подождите 5-10 минут нагрузки
/timings paste

Ссылка покажет, какие плагины/тики съедают CPU и память.

6.2 Подключение JMX (для VisualVM / JConsole)

Добавьте в JAVA_OPTS (только для временной диагностики, не для постоянной работы):

-Dcom.sun.management.jmxremote
-Dcom.sun.management.jmxremote.port=9010
-Dcom.sun.management.jmxremote.authenticate=false
-Dcom.sun.management.jmxremote.ssl=false
-Djava.rmi.server.hostname=ВАШ_ВНЕШНИЙ_IP

В панели proxify.cloud → «Сеть» → «Фаервол» откройте порт 9010 только для вашего IP. Подключитесь через VisualVM (скачайте с visualvm.github.io) → File → Add JMX Connection → IP:9010. Смотрите вкладку Heap Dump и Monitor -> Metaspace.

6.3 Автоматические дампы при OOM

Добавьте в JAVA_OPTS:

-XX:+HeapDumpOnOutOfMemoryError
-XX:HeapDumpPath=/home/minecraft/dumps/heap_%p_%t.hprof

Создайте папку:

mkdir -p /home/minecraft/dumps && chown minecraft:minecraft /home/minecraft/dumps

После краша анализируйте .hprof через Eclipse MAT (Memory Analyzer Tool) — найдет утечки в конкретных классах плагинов.

7. Проверка плагинов и модов на утечки

Часто виноват конкретный плагин (например, плохо написанный WorldGuard флаг, Dynmap рендерер, бэкап-плагин, держащий файлы в памяти).

7.1 Метод "Половинного деления"

  1. Остановите сервер