Стек и куча в Java

Стек и куча — разные области runtime-памяти JVM. У каждого потока свой Java stack, а heap обычно общий для потоков и управляется сборщиком мусора.

Что хранится в стеке

Вызов метода создаёт frame. В нём находятся локальные переменные, операндный стек, служебные данные и ссылка на constant pool текущего класса. После возврата frame снимается целиком.

static int length(String text) {
    int result = text.length();
    return result;
}

В frame лежат локальная ссылка text и значение result. Сам объект String обычно находится в heap. Формула «примитивы всегда в стеке, объекты всегда в куче» неточна: примитивное поле является частью объекта в heap, а JIT может скаляризовать объект и вообще не выделить его в наблюдаемой куче.

Что хранится в куче

В heap размещаются обычные объекты и массивы. Достижимость объектов определяет Garbage collector. Куча может быть поделена на регионы или поколения — точное устройство зависит от выбранного GC.

Кроме heap JVM использует и другие области:

ОбластьСодержимое
Metaspaceметаданные загруженных классов
Code cacheмашинный код, созданный JIT
Native memoryструктуры JVM и нативных библиотек
Direct buffersпамять вне heap для некоторых операций ввода-вывода

Типичные сбои

  • StackOverflowError — слишком глубокая рекурсия или слишком маленький стек;
  • OutOfMemoryError: Java heap space — не удалось выделить объект в heap;
  • OutOfMemoryError: Metaspace — удерживается слишком много метаданных классов;
  • нехватка native memory может возникнуть даже при свободном heap.

Размер heap задают, например, -Xms и -Xmx, размер стека потока — -Xss. Параметры влияют на поведение, но не заменяют измерение профилером.

Стек относится к устройству runtime, а Java Memory Model задаёт правила наблюдения операций потоками — это разные понятия.

Вопросы для собеседования

  1. Есть ли отдельный stack у каждого потока? Да.
  2. Где хранится ссылка на объект? Зависит от места: локальная ссылка может быть во frame, поле-ссылка — внутри объекта в heap.
  3. Всегда ли new приводит к выделению в heap? Семантически создаёт объект, но JIT может устранить выделение, если объект не утекает.
  4. Что очищает stack? Возврат из метода снимает frame; GC для этого не нужен.
  5. Находится ли Metaspace в heap? Нет, это отдельная native memory.
  6. Почему свободный heap не исключает OOM? Закончиться может Metaspace, direct/native memory или лимит процесса.