Что такое Metaspace в JVM?

Ответ

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, как и следить за обычной кучей. А то будете потом, как Герасим, с мешком на речку ходить — только топить будете не собачку, а свой продакшен-сервер.