Ответ
Metaspace — это область нативной (внекучевой) памяти, используемая JVM начиная с Java 8 для хранения метаданных загруженных классов. Она заменила собой PermGen (Permanent Generation), которая располагалась в куче.
Что хранится в Metaspace?
- Структуры классов (Class metadata): имена, методы, поля, сигнатуры.
- Байт-код методов.
- Константы пула строк (String Table), относящиеся к классам.
- Аннотации.
- Оптимизированный код, сгенерированный JIT-компилятором.
| Ключевые отличия от PermGen: | Характеристика | PermGen (до Java 7) | Metaspace (Java 8+) |
|---|---|---|---|
| Расположение | Часть кучи Java (Heap) | Нативная память ОС (вне кучи) | |
| Размер | Фиксированный, задаётся -XX:MaxPermSize |
Динамический, ограничен доступной нативной памятью | |
| Очистка | Полная сборка мусора (Full GC) | Сборка мусора, вызванная нехваткой памяти в Metaspace | |
| Причина OutOfMemoryError | OutOfMemoryError: PermGen space |
OutOfMemoryError: Metaspace |
Управление размером Metaspace (флаги JVM):
# Начальный размер Metaspace (по умолчанию зависит от платформы)
-XX:MetaspaceSize=64m
# Максимальный размер Metaspace (по умолчанию не ограничен, используется вся нативная память)
-XX:MaxMetaspaceSize=256m
# Частота сборки мусора класса (Class Unloading)
-XX:MinMetaspaceFreeRatio=40
-XX:MaxMetaspaceFreeRatio=70
Типичная проблема: утечка памяти в Metaspace. Возникает, когда загрузчики классов (ClassLoader) не выгружаются, и метаданные накапливаются. Частая причина в серверах приложений (Tomcat, JBoss) при частом redeploy приложений.
Почему это важно? Metaspace устранила главную проблему PermGen — необходимость заранее угадывать размер для хранения метаданных, что снижало риск OutOfMemoryError. Однако теперь утечки могут потреблять всю нативную память системы, поэтому мониторинг и настройка лимитов остаются критически важными.
Ответ 18+ 🔞
Давай разберём эту штуку, которая у всех на слуху, но как-то по-собачьи непонятно. Metaspace, блядь. Представь себе, что до Java 8 у нас был такой старый, занюханный чулан — PermGen. Туда складывали всякий хлам: имена классов, методы, поля, этот вот весь бюрократический аппарат программы. И чулан был фиксированного размера, и если ты туда наскрёб слишком много классов (особенно в том же Tomcat'е, когда приложение двадцать раз перезаливаешь), он просто брал и говорил: «Всё, пиздец, OutOfMemoryError: PermGen space». И привет, перезапуск сервера.
И тут пришла Java 8 и говорит: «Да пошёл ты нахуй с этим чуланом!». И сделала Metaspace. А суть в чём? Теперь этот хлам — метаданные классов — складывают не в кучу (Heap), а в нативную память ОС. То есть прямо в память твоего компьютера, без посредников. И размер у него теперь динамический, по умолчанию — хоть всю оперативку сожри, если позволишь.
Что там валяется, в этой Metaspace:
- Ну, сами классы, их имена, методы, поля — вся эта скучная документация.
- Байт-код, который твои методы выполняют.
- Константы из String Pool, которые к классам привязаны.
- Аннотации, эти модные штуки.
- Оптимизированный код от JIT-компилятора, который пытается сделать твою программу быстрее.
Чем это лучше старого чулана?
Раньше ты в -XX:MaxPermSize=128m пытался угадать, какого размера тебе нужен чулан. Не угадал — получи по ебалу с ошибкой. Теперь Metaspace сама расширяется, сколько надо. Но, внимание, ебаный подвох! Если ты ей не поставишь лимит (-XX:MaxMetaspaceSize), она может тихо и мирно сожрать всю свободную память на машине, и операционка просто прибьёт твой Java-процесс. Красиво, да?
Как этим рулить, чтобы не было мучительно больно:
# С какого размера начинать (дефолт платформозависимый, но лучше явно указать)
-XX:MetaspaceSize=64m
# А вот это, сука, самое главное — лимит! Не дай ей распоясаться.
-XX:MaxMetaspaceSize=256m
Где собака зарыта? В утечках, блядь! Классика жанра — сервера приложений вроде Tomcat. Ты задеплоил приложение, потом его удалил, задеплоил новую версию. Старые классы должны выгрузиться. Но если где-то осталась ссылка на их ClassLoader (какой-нибудь хитрый кэш, или библиотека кривая), то метаданные так и будут висеть в Metaspace, как призраки. И она будет расти, расти, пока не упрётся в лимит или в потолок оперативки. И тогда — OutOfMemoryError: Metaspace. И опять здравствуй, аварийный перезапуск в три часа ночи.
Так что вывод, ёпта, простой: PermGen убили не просто так, это было больное место. Metaspace — гибче и умнее. Но это не значит, что про неё можно забыть. Поставить разумный MaxMetaspaceSize и мониторить её потребление — это такой же must have, как и следить за обычной кучей. А то будете потом, как Герасим, с мешком на речку ходить — только топить будете не собачку, а свой продакшен-сервер.