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 может съесть всю память ОС при утечке загрузчиков классов).