Почему Java использует кучу для выделения памяти? - PullRequest
13 голосов
/ 07 мая 2010

Я только что прочитал это утверждение в книге Java, в которой говорится, что объекты в Java находятся в куче. Используется ли куча, потому что это лучший способ хранить данные и быстро их извлекать?

У меня есть только представление о том, что структуры данных являются новичками. Я имею в виду, почему бы не стек или что-то еще?

Ответы [ 7 ]

14 голосов
/ 07 мая 2010

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

3 голосов
/ 07 мая 2010

Куча используется только виртуальной машиной для выделения и освобождения блоков памяти.Для доступа к объектам вы используете ссылку на блок памяти (эта ссылка находится в стеке).Jvm не разрешает прямой доступ к памяти (как в C / C ++).

2 голосов
/ 07 мая 2010

Это артефакт базовой вычислительной модели. Память для операционной системы выглядит как большое, в основном непрерывное пространство, в котором данные могут быть прочитаны и записаны по адресу. Операционная система позволяет процессам захватывать блок памяти (большое непрерывное пространство, обычно не менее одной страницы из пары К) и делать это по своему усмотрению, используя адреса памяти и операции чтения / записи.

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

Помните, что он действует как "куча" для программиста, потому что это дает вам необходимую гибкость, но его не нужно реализовывать как таковое. Это часть памяти, управляемая сборщиком мусора, и есть куча структур данных, которые он использует для своей работы, которые вы можете или не могли бы рассматривать как часть кучи, т.е. это память, используемая и выделяемая JVM, но обычно в этом контексте «куча» считается только памятью, доступной программисту.

1 голос
/ 07 мая 2010

Поскольку объекты в Java часто переживают область, в которой они были созданы, в этот момент стековый фрейм, созданный для области, перестает существовать.

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

1 голос
/ 07 мая 2010

Почему бы не хранить объекты в стеке? Хорошо, что происходит со стеком после того, как текущий выполняемый метод прекращает выполнение?

1 голос
/ 07 мая 2010

Поскольку Java использует сборщик мусора для восстановления памяти, в отличие от C и C ++. В этих языках имеет смысл использовать стек для локальных переменных *. В Java нет концепции (локальной) переменной, выходящей из области видимости, только на нее больше не ссылаются, что делает ее пригодной для сборки мусора (что должно произойти когда-то после этой точки).

*, что для ясности не означает, что в C / C ++ не было кучи, или что вы не можете использовать семейство malloc / new для распределения переменных в использоваться исключительно в пределах локальной области.

0 голосов
/ 11 июля 2014

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

Если бы Java позволяла объектам явно находиться в стеке, что произойдет, если метод вернется? Что произойдет с любыми ссылками на локальный объект, содержащимися в любых нелокальных объектах?

  • Разработчики Java могли бы решить, что некоторые ссылки могут быть недействительными , приводя к неопределенному поведению в случае разыменования. Так же, как указатель в C / C ++. Разработчики Java, похоже, пошли на многое, чтобы избежать неопределенного поведения.

  • Разработчики Java могли указать, что все ссылки на локальный объект стали нулевыми. Найти все эти ссылки было бы сложно. И это приведет к тому, что будет трудно найти ошибки, вызванные ссылками, которые, как предполагалось, не равны нулю, внезапно станут нулевыми. Неизменяемые объекты, содержащие ссылки на объекты, были бы невозможны. И механизм уведомления, который устанавливает ссылки на нуль, должен работать между потоками. Стоимость всего этого будет намного выше, чем преимущество локального хранилища.

  • Один из разработчиков языков, Джеймс Гослинг, имеет опыт работы с Lisp, и это влияние проявляется в идее, что удаление объектов просто оставлено сборщику мусора, а компилятор или среда времени выполнения оптимизируют удаление объектов (escape анализ) если возможно.

...