Где размещается ссылка на переменную, в стеке или в куче?

У меня есть вопрос

Что происходит, например, когда я объявляю переменную внутри метода.

void myMethod() {
    Ship myShip = new Ship();
}

Где размещается ссылка myShip, в стеке или в куче?

Я думаю, что в стеке, но я запутался, потому что я читал в книге по программированию игр J2ME "Класс Java создается в куче Java"

Все классы Java?

заранее спасибо


person iberck    schedule 17.05.2009    source источник
comment
Этот вопрос немного не ясен. Это может быть либо Где ссылка на myShip хранится в памяти? или Где хранится в памяти объект, на который указывает myShip? Концептуальным ответом на первое является стек, а концептуальным ответом на второе — куча, за исключением оптимизаций и сумасшедших реализаций, и есть ответы, отвечающие на оба варианта.   -  person Casey Rodarmor    schedule 16.02.2012


Ответы (4)


myShip является ссылкой на объект Ship, myShip находится в стеке вызова метода, который называется «стеком». Когда вызывается метод, блок памяти помещается на вершину стека, в этом блоке памяти есть место для всех примитивов (int, float, boolean и т. д.) и ссылок на объекты метода, которые включают параметры метода. Куча — это место, где выделяется память для реальных объектов.

Таким образом, myShip находится в стеке, а объект Ship — в куче.

Обратите внимание, что каждый поток имеет свой собственный стек, но совместно использует кучу.

person nash    schedule 17.05.2009

Java действительно делает вещи немного по-другому. ссылка в основном находится в стеке. Память для объекта выделяется в том, что проходит для кучи. Однако реализация выделяемой памяти не совсем похожа на то, как куча реализована в модели C/C++.

Когда вы создаете такой новый объект, он фактически помещает имя в таблицу ссылок для этой области. Это очень похоже на указатель на объект в C++. Когда это выходит за рамки, эта ссылка теряется; на выделенную память больше не ссылаются, и она может быть удалена сборщиком мусора.

person Charlie Martin    schedule 17.05.2009
comment
Что, если бы это было просто Ship ship; Это означает, что ссылка на корабль находится в стеке, но объект не создан. Но значит ли это, что в этот момент загружен класс Ship? - person Joeblackdev; 14.08.2011
comment
Действительно? Я думал, что при этом создается ссылка на корабль, инициализированная нулевым значением. Есть ли разница? - person Joeblackdev; 14.08.2011
comment
@CharlieMartin: Вы ошибаетесь, ‹code› Корабельный корабль;‹/code› не стройте Корабль! Переменная просто инициализируется нулем. - person tibo; 17.05.2012
comment
Если это локальная переменная (т. е. переменная в методе), она не инициализируется значением null, если только вы явно не установите для нее значение null! - person Bombe; 12.07.2013
comment
Я проверил код: ‹code›Ship ship; System.out.println(+ship)‹/code›, и это событие не компилируется с использованием javac 1.8.0_31, оно говорит мне, что корабль, возможно, не был инициализирован, поэтому я думаю, что @Bombe прав - person Vit Bernatik; 29.04.2015

В настоящее время все объекты Java размещены в куче. Ходят разговоры о том, что Java 7 может избежать анализа и иметь возможность размещать в стеке, но я не знаю, завершено ли это предложение. Вот RFE.

Изменить: очевидно, это уже в ранних сборках JDK 7. (В статье говорится, что это также будет в JDK 6u14, но я не могу найти подтверждения.)

person Michael Myers    schedule 17.05.2009
comment
Однако escape-анализ не влияет на семантику кода, поэтому никогда не нужно полагаться на его существование или предполагать его существование. - person bdonlan; 19.05.2009
comment
@bdonlan: Правильно, однако анализ побега (реализованный начиная с Java SE 6u23, кстати) действительно способствует тому, что сегодняшняя Java не является хромой уткой, какой она была 15 лет назад. - person Franz D.; 07.03.2015

Условно объект попадает в "кучу". Затем, поскольку это локальная ссылка метода, фактическая ссылка будет находиться в стеке. Под «стеком» мы подразумеваем собственный стек потоков (т. е. тот же стек, в котором будет размещена локальная переменная в C) по крайней мере в случае виртуальной машины Sun, но я не думаю, что это на самом деле требование (JVM просто нужно иметь какое-то абстрактное понятие «кадров стека», которые он выделяет при каждом вызове метода, будь то из собственного стека или нет).

Но... на современных виртуальных машинах (за возможным исключением более простых встроенных/мпбильных виртуальных машин) на самом деле нет такой вещи, как "куча". На практике существуют различные области кучи. Самый простой из них, как правило, похож на «мини-стек», предназначенный для быстрого выделения объектов, которые не будут долго зависать и, вероятно, могут быть освобождены почти сразу.

Как упоминалось в другом авторе, высокооптимизированная JVM может в принципе размещать объектные данные в стеке, и для этого есть определенные предложения. Хотя, как также упоминалось в одной из ссылок, критика этого заключается в том, что быстрая куча «eden» в любом случае почти похожа на стек (только не «стек»).

person Neil Coffey    schedule 17.05.2009