- Что такое PermGen и почему она важна
- Почему возникает ошибка PermGen error в Minecraft и веб-приложениях
- Как понять, что у вас именно PermGen error
- Практические шаги для решения PermGen error
- Таблица основных JVM опций для борьбы с PermGen error
- Как избежать PermGen error в будущем
- Пример из жизни: как я победил PermGen error
- Итог
- Полезные ссылки
Если вы столкнулись с ошибкой PermGen error в Minecraft или при работе с Java-вебприложениями, то вы попали по адресу. В этом посте мы разберём, что такое PermGen, почему возникает ошибка OutOfMemoryError: PermGen space, как её диагностировать и, главное, как избавиться от неё раз и навсегда. Приготовьтесь к яркому путешествию в мир Java-памяти, class loader-ов и хитростей Tomcat!
Что такое PermGen и почему она важна
PermGen (Permanent Generation) — это специальная область памяти в JVM, где хранятся описания классов Java и метаданные. Представьте PermGen как шкафчик с костюмами для ваших Java-классов: каждый раз, когда веб-приложение запускается или перезапускается, туда загружаются новые костюмы. Если шкафчик переполнен, JVM выдает ошибку OutOfMemoryError: PermGen space — и тут начинается веселье.
В Java 8 PermGen заменили на Metaspace, который динамически расширяется, но проблема с утечками памяти и переполнением осталась актуальной, особенно для серверов с Tomcat и веб-приложениями.
Почему возникает ошибка PermGen error в Minecraft и веб-приложениях
Основные причины:
- Перезапуск веб-приложения без перезапуска сервера. При этом старые классы не выгружаются из PermGen, а новые загружаются поверх.
- Утечки памяти из-за неправильной работы class loader-ов. Если на классы ссылаются объекты вне веб-приложения, сборщик мусора не может их убрать.
- Неостановленные потоки (Threads), запущенные из веб-приложения, которые продолжают держать ссылки на class loader.
- ThreadLocal-переменные, которые не очищаются, создавая цепочку ссылок и блокируя выгрузку классов.
Как понять, что у вас именно PermGen error
Признаки:
- В логах сервера появляется ошибка
java.lang.OutOfMemoryError: PermGen space
. - Сервер Minecraft или веб-приложение падает с сообщением о нехватке PermGen памяти.
- При перезапуске приложения ошибка повторяется всё чаще.
- В логах Tomcat можно увидеть предупреждения о неостановленных потоках или ThreadLocal.
Практические шаги для решения PermGen error
1. Увеличьте размер PermGen памяти
Добавьте в параметры JVM:
-XX:MaxPermSize=256m
Это отсрочит проблему, но не решит её полностью.
2. Используйте правильный сборщик мусора
Для Java 7 + Tomcat 7 рекомендуется включить:
-XX:+UseConcMarkSweepGC
-XX:+CMSClassUnloadingEnabled
-XX:+CMSPermGenSweepingEnabled
Эти опции помогут JVM лучше выгружать классы из PermGen.
3. Остановите и очистите неостановленные потоки
В логах Tomcat ищите сообщения типа:
SEVERE: The web application [...] appears to have started a thread named [...] but has failed to stop it.
Найдите и исправьте код, который не останавливает потоки при остановке приложения. Например, вызовите Thread#interrupt()
или установите флаг остановки.
4. Очистите ThreadLocal-переменные
ThreadLocal — это ловушка для утечек, если не вызывать remove()
после использования. Проверьте, что для каждого put()
вызывается remove()
.
5. Используйте встроенные средства Tomcat
- Кнопка Find leaks в Tomcat Manager Application покажет подозрительные утечки.
- Включите в
server.xml
слушательJreMemoryLeakPreventionListener
с параметромAWTThreadProtection=true
для защиты от специфических утечек.
6. Анализируйте память с помощью VisualVM
VisualVM — бесплатный профайлер из JDK, который поможет:
- Сделать heap dump.
- Выполнить OQL-запросы для поиска WebappClassLoader, который не выгружается.
- Найти ссылки, мешающие сборщику мусора.
Пример OQL-запроса:
select x from org.apache.catalina.loader.WebappClassLoader x
Таблица основных JVM опций для борьбы с PermGen error
Опция | Назначение | Рекомендуется для |
---|---|---|
-XX:MaxPermSize=256m |
Увеличение максимального размера PermGen | Все JVM до Java 8 |
-XX:+UseConcMarkSweepGC |
Включение CMS сборщика мусора | Java 7 + Tomcat 7 |
-XX:+CMSClassUnloadingEnabled |
Позволяет выгружать классы при CMS сборке мусора | Java 7 + Tomcat 7 |
-XX:+CMSPermGenSweepingEnabled |
Оптимизация очистки PermGen | Java 7 + Tomcat 7 |
JreMemoryLeakPreventionListener |
Защита от известных утечек памяти в Tomcat | Tomcat серверы |
AWTThreadProtection=true |
Защита от утечек потоков AWT | Tomcat серверы |
Как избежать PermGen error в будущем
- Перезапускайте сервер, а не только веб-приложения, если возможно.
- Следите за корректным завершением потоков и очисткой ThreadLocal.
- Используйте современные версии Java (Java 8 и выше), где PermGen заменён на Metaspace.
- Регулярно анализируйте логи и память с помощью инструментов профилирования.
- Настраивайте JVM параметры под нагрузку и особенности вашего приложения.
Пример из жизни: как я победил PermGen error
В одном из проектов сервер Minecraft регулярно падал с ошибкой PermGen. Анализ логов показал, что поток AWT-Windows
не останавливается. Добавил в server.xml
Tomcat параметр:
<Listener className="org.apache.catalina.core.JreMemoryLeakPreventionListener" AWTThreadProtection="true" />
Проблема исчезла! Также проверил код на наличие ThreadLocal без вызова remove()
— исправил. После этого сервер работал стабильно без падений.
Итог
PermGen error — это вызов для разработчика и администратора. Понимание архитектуры JVM, class loader-ов и правильная настройка JVM помогут вам избавиться от этой ошибки и сделать ваш Minecraft-сервер или веб-приложение стабильным и быстрым.
Полезные ссылки
- Подробный разбор PermGen error на Habr
- Обсуждение PermGen error на форуме ru-minecraft.ru
- Тема на rubukkit.org с советами по PermGen
- Документация Tomcat по class loader-ам
- Tomcat Manager и поиск утечек памяти
- JreMemoryLeakPreventionListener в Tomcat
Пусть ваш сервер будет крепким, а память — чистой! Если PermGen error снова постучится в дверь — вы теперь знаете, как с ним справиться.