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