Что такое Non-Heap память в контексте JVM?

«Что такое Non-Heap память в контексте JVM?» — вопрос из категории Java Core, который задают на 10% собеседований Java Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Non-Heap память (внекучная память) в JVM — это область памяти, не управляемая стандартным сборщиком мусора (Garbage Collector). Она используется для служебных данных самой виртуальной машины.

Основные компоненты Non-Heap памяти:

  1. Metaspace (с Java 8): Хранит метаданные загруженных классов (структуры классов, методы, поля, байт-код). Заменил собой PermGen (Permanent Generation). Размер динамически меняется, ограничен параметром MaxMetaspaceSize.
  2. Code Cache: Область для хранения скомпилированного машинного кода JIT-компилятором (Just-In-Time).
  3. Память потоков (Thread Stacks): Выделяется под стек каждого потока.
  4. Память вне кучи, управляемая приложением:
    • Direct ByteBuffers: Память, выделяемая вызовом ByteBuffer.allocateDirect(), обходящая Java Heap и работающая напрямую с нативной памятью ОС.
    • Нативные библиотеки: Память, выделяемая через JNI (Java Native Interface).

Пример утечки в Metaspace (ClassLoader leak):

// Динамическая генерация и загрузка классов
while (true) {
    ClassLoader cl = new CustomClassLoader();
    Class<?> c = cl.loadClass("com.example.GeneratedClass");
    // Если классы/ClassLoader'ы не выгружаются, Metaspace заполняется
}

Ключевые параметры JVM для настройки:

  • -XX:MetaspaceSize — начальный размер Metaspace.
  • -XX:MaxMetaspaceSize — максимальный размер Metaspace.
  • -XX:ReservedCodeCacheSize — максимальный размер Code Cache.
  • -XX:MaxDirectMemorySize — лимит для Direct ByteBuffers.

Мониторинг:

  • Через JMX (MemoryMXBean, MemoryPoolMXBean).
  • Утилитой jcmd: jcmd <pid> VM.native_memory.
  • В профилировщиках (VisualVM, JMC, async-profiler).