Gymterview
middle

Что такое Metaspace и чем он отличается от PermGen

Metaspace — это область памяти JVM (начиная с Java 8, JEP 122), расположенная в native memory за пределами heap, предназначенная для хранения метаданных загруженных классов. Metaspace заменил PermGen, который имел фиксированный размер и часто вызывал OutOfMemoryError: PermGen space.

Сравнение PermGen и Metaspace

Характеристика PermGen (Java 7 и ранее) Metaspace (Java 8+)
Расположение Внутри heap JVM В native memory (вне heap)
Размер по умолчанию Фиксированный (64-256 MB) Ограничен только доступной памятью ОС
Параметр ограничения -XX:MaxPermSize -XX:MaxMetaspaceSize
Рост Не растёт автоматически Динамически расширяется
GC Собирается при Full GC Собирается при достижении порога (-XX:MetaspaceSize)

Что хранится в Metaspace

  • Метаданные загруженных классов (структуры Klass)
  • Constant pool (пул констант) классов
  • Аннотации и сигнатуры методов
  • Байт-код методов
  • Данные о виртуальных таблицах методов (vtable, itable)

Интернированные строки (String intern pool) были перенесены из PermGen в heap ещё в Java 7 (JEP 2495).

Настройка Metaspace

Параметры JVM для настройки Metaspace
# Установить начальный порог для запуска GC Metaspace
-XX:MetaspaceSize=256m

# Установить максимальный размер Metaspace
-XX:MaxMetaspaceSize=512m

# Минимальное свободное пространство после GC (в процентах)
-XX:MinMetaspaceFreeRatio=40

# Максимальное свободное пространство после GC (в процентах)
-XX:MaxMetaspaceFreeRatio=70
Мониторинг Metaspace
# Посмотреть использование Metaspace через jstat
jstat -gcmetacapacity <pid>

# Через jcmd
jcmd <pid> VM.metaspace

Частые ошибки

  • Забывают установить -XX:MaxMetaspaceSize в production — при утечке загрузчиков классов процесс может быть убит OOM Killer ОС
  • Путают MetaspaceSize (порог для первого GC) с MaxMetaspaceSize (жёсткий лимит)
  • Пытаются использовать параметры PermGen (-XX:MaxPermSize) на Java 8+ — они игнорируются с предупреждением

На собеседовании: главное отличие — Metaspace живёт в native memory и растёт динамически, а PermGen имел фиксированный размер в heap. Обязательно упомяните, что String intern pool перенесён в heap ещё в Java 7. Частая ловушка — вопрос о том, что будет, если не задать MaxMetaspaceSize (ответ: Metaspace может съесть всю память ОС при утечке загрузчиков классов).