В чем разница heap и stack в Java
Что проверяют
Понимаете ли вы, что в стеке лежит ссылка, а объект в куче, и знаете ли исключение из этого правила.
Как отвечать
Стек свой у каждого потока. В нём лежат кадры вызовов: локальные переменные примитивных типов, ссылки на объекты, адрес возврата. Работает по принципу «последним пришёл, первым ушёл», выделение это сдвиг указателя, освобождение происходит само при выходе из метода. Размер ограничен (задаётся -Xss), и при слишком глубокой рекурсии получается StackOverflowError.
Куча одна на всю виртуальную машину и общая для потоков. В ней живут все объекты и массивы, а освобождает их сборщик мусора. Куча разделена на поколения: новые объекты создаются в молодом, пережившие несколько сборок переезжают в старое. Переполнение даёт OutOfMemoryError, размер задаётся -Xmx.
Правило: объект всегда в куче, в стеке только ссылка на него. Даже локальная переменная типа объекта это ссылка в кадре, указывающая в кучу.
Из этого правила есть исключение, и знание о нём отличает сильный ответ: скалярная замена после анализа побега. Если JIT-компилятор доказал, что объект не покидает метод, он может не создавать его вовсе, разложив поля по регистрам и стеку. То есть «объекты всегда в куче» верно на уровне модели, но не всегда на уровне машинного кода.
Что стоит добавить:
- метапространство это отдельная область вне кучи для метаданных классов, оно пришло на смену области постоянных объектов;
- пул строк с версии 7 живёт в куче, а не в области постоянных объектов;
- потокобезопасность: стек по определению приватен, поэтому локальные переменные не требуют синхронизации, а всё, что в куче и доступно нескольким потокам, требует.
Где спотыкаются
Считают, что примитивное поле объекта лежит в стеке. Оно лежит в куче вместе с объектом, в стеке только локальные примитивы.
Не знают про анализ побега.
Путают StackOverflowError и OutOfMemoryError.
Думают, что стек общий для потоков.