Где в памяти Java хранятся вызовы процедур и передаваемые параметры, включая ссылки на объекты
Что проверяют
Понимаете ли вы устройство памяти JVM на уровне стека и кучи и то, что Java передаёт аргументы только по значению, включая ссылки. Следом почти всегда спрашивают: «Если внутри метода присвоить параметру новый объект, увидит ли это вызывающий код?», и что такое StackOverflowError.
Как отвечать
- стек потока: у каждого потока свой стек. На каждый вызов метода создаётся фрейм, в нём массив локальных переменных, стек операндов и ссылка на пул констант класса. Параметры лежат в том же массиве локальных переменных, первыми, а у метода экземпляра нулевой слот занимает
this; - примитивы и ссылки:
int,doubleи другие примитивы лежат во фрейме значениями. Для объекта во фрейме лежит только ссылка, сам объект в куче; - передача по значению: при вызове ссылка копируется. Через копию можно изменить состояние объекта, и это увидят все, но
param = new ArrayList<>()меняет только локальную копию; - куча: объекты и массивы, ей управляет сборщик мусора. Метаданные классов с Java 8 живут в Metaspace, вне кучи;
- размер стека: задаётся
-Xss, на 64-битном Linux по умолчанию обычно 1 МБ. Слишком глубокая рекурсия заканчиваетсяStackOverflowError, а неOutOfMemoryError.
Сильный ответ добавляет две оговорки. JIT с escape analysis может не выделять объект в куче, если тот не покидает метод: поля раскладываются по регистрам и локальным слотам (scalar replacement). А у виртуальных потоков из Java 21 фреймы на время отсоединения от несущего потока копируются в кучу, поэтому миллион виртуальных потоков не требует миллиона стеков по мегабайту.
Где спотыкаются
Говорят, что объекты в Java передаются по ссылке. Метод swap двух параметров, который ничего не меняет снаружи, опровергает это за минуту.
Называют «все объекты всегда в куче» законом JVM. Это модель языка, а JIT после escape analysis вправе обойтись без выделения.
Связывают утечку памяти со стеком. Фрейм исчезает при выходе из метода сам, а утечка в Java это ненужные объекты в куче, которые остаются достижимыми: статическая коллекция, кеш без вытеснения, забытый слушатель.