Если вы когда-нибудь натыкались на загадочную ошибку java.lang.OutOfMemoryError: PermGen space в Minecraft или других Java-приложениях, то этот пост — именно для вас. Мы разберём, что такое PermGen, почему она важна, как она связана с Minecraft, и почему в Java 8 её заменили на Metaspace. А ещё расскажем, как избежать типичных проблем с памятью, которые могут свести с ума любого разработчика или администратора сервера.


Что такое PermGen и зачем она нужна

PermGen (Permanent Generation) — это особая область памяти в JVM, где хранятся метаданные классов. Представьте, что Minecraft — это огромный конструктор из блоков, а PermGen — это склад с инструкциями, как эти блоки собирать. В PermGen JVM хранит:

  • Описания загруженных классов (их метаданные)
  • Статические переменные и ссылки на статические объекты
  • Байткод и информацию JIT-компилятора
  • До Java 7 — пул строк (string pool)

PermGen располагалась вне основной кучи (heap), но всё равно в пределах памяти JVM. Для 64-битных JVM максимальный размер PermGen по умолчанию был около 82 Мб — не так уж и много, если учесть, сколько классов и библиотек может загрузить Minecraft-сервер.


Почему PermGen вызывает проблемы в Minecraft и других вебприложениях

Ошибка OutOfMemoryError: PermGen space возникает, когда PermGen переполняется. В Minecraft это может случиться, если:

  • Часто перезагружаются плагины или моды, которые загружают новые классы
  • Есть утечки памяти из-за неправильного освобождения ресурсов
  • Используются старые версии Java (до 8), где PermGen ограничена по размеру

Пример из жизни: вы запускаете сервер Minecraft с кучей плагинов, и после нескольких перезапусков плагинов сервер падает с ошибкой PermGen. Почему? Потому что старые class loader-ы, которые загружали классы плагинов, не были корректно выгружены, и PermGen забита "мусором".


Управление размером PermGen

Для контроля PermGen в JVM до Java 8 использовались параметры:

Параметр Описание Пример использования
-XX:PermSize Минимальный размер PermGen -XX:PermSize=64m
-XX:MaxPermSize Максимальный размер PermGen -XX:MaxPermSize=128m

Увеличение MaxPermSize — частое решение, но оно лишь отсрочит проблему, если есть утечки.


Почему PermGen убрали в Java 8 и что такое Metaspace

В Java 8 PermGen была полностью удалена и заменена на Metaspace. Главное отличие:

  • PermGen — область памяти внутри JVM, ограниченная по размеру
  • Metaspace — область памяти, выделяемая из нативной памяти ОС, то есть вне JVM heap

Это значит, что Metaspace может динамически расширяться, и вероятность ошибки OutOfMemoryError из-за метаданных классов значительно снижается.


Как работает Metaspace и его параметры

Metaspace хранит те же данные, что и PermGen, но теперь:

  • Память выделяется из системной памяти, а не из фиксированного пула JVM
  • Размер Metaspace по умолчанию растёт автоматически

Параметры управления:

Параметр Описание Пример использования
-XX:MetaspaceSize Начальный размер Metaspace -XX:MetaspaceSize=64m
-XX:MaxMetaspaceSize Максимальный размер Metaspace (по умолчанию не ограничен) -XX:MaxMetaspaceSize=256m
-XX:MinMetaspaceFreeRatio Минимальный процент свободной памяти после GC -XX:MinMetaspaceFreeRatio=40
-XX:MaxMetaspaceFreeRatio Максимальный процент свободной памяти после GC -XX:MaxMetaspaceFreeRatio=70

Min/MaxMetaspaceFreeRatio помогают JVM управлять размером Metaspace, чтобы не выделять слишком много или слишком мало памяти.


Сборка мусора и Metaspace — как это снижает риск ошибок

В PermGen сборщик мусора мог не выгружать классы, если на них оставались ссылки, что приводило к утечкам и ошибкам. В Metaspace сборка мусора стала эффективнее:

  • JVM автоматически выгружает ненужные классы, когда память заполняется
  • Метаданные классов теперь не ограничены жёстким лимитом, что снижает OutOfMemoryError

Почему Minecraft и вебприложения страдают от утечек PermGen/Metaspace

Основная причина — утечки class loader-ов. В Minecraft это может быть:

  • Плагины, которые создают новые class loader-ы при перезагрузке, но не освобождают старые
  • Потоки, запущенные плагинами, которые не останавливаются и держат ссылки на class loader
  • Использование ThreadLocal, где объекты не удаляются, и ссылки остаются

Веб-приложения на Tomcat сталкиваются с теми же проблемами, и для них есть специальные инструменты.


Как обнаружить и исправить утечки памяти в PermGen/Metaspace

Инструменты и методы

  • Tomcat Manager: кнопка "Find leaks" показывает подозрительные веб-приложения
  • JreMemoryLeakPreventionListener: слушатель в Tomcat для предотвращения известных утечек
  • Логи Tomcat: сообщения о потоках и ThreadLocal, которые не были удалены
  • VisualVM: профайлер для анализа heap dump, OQL-запросы для поиска WebappClassLoader

Пример OQL-запроса для VisualVM

select x from org.apache.catalina.loader.WebappClassLoader x

Это позволяет найти объекты class loader-ов, которые не были выгружены.


Практические советы для Minecraft-серверов и Java-приложений

  • Используйте Java 8 и выше, чтобы избежать ограничений PermGen
  • Настраивайте параметры MetaspaceSize и MaxMetaspaceSize, если сервер активно загружает и выгружает плагины
  • Следите за потоками, которые запускают плагины, и корректно их останавливайте
  • Избегайте использования ThreadLocal без вызова remove()
  • Периодически профилируйте память с помощью VisualVM или аналогов
  • При использовании Tomcat включайте опции -XX:+UseConcMarkSweepGC, -XX:+CMSClassUnloadingEnabled для улучшения сборки мусора

Итоги и что важно помнить

Тема Ключевой вывод
PermGen Ограниченная область памяти для метаданных классов, вызывает ошибки OutOfMemoryError
Metaspace Замена PermGen в Java 8, динамическое выделение памяти из ОС
Утечки памяти Часто связаны с неправильным управлением class loader-ами и потоками
Инструменты Tomcat Manager, VisualVM, логи помогают выявлять и устранять утечки
Практика Используйте современные JVM, следите за потоками и ThreadLocal, настраивайте параметры памяти

Полезные ссылки


Теперь вы знаете, что такое PermGen в Minecraft и Java, почему она может стать головной болью, и как Metaspace решает многие проблемы. Помните: правильное управление памятью — залог стабильной работы вашего сервера и приложений!