где массив сохраняется в памяти в Java? - PullRequest
12 голосов
/ 10 августа 2011

Если у меня есть функция, которую в этой функции я объявляю:

Object arr[] = new Object[20];

Где хранится arr и весь массив?кучи?стек?Имеет ли значение, если объявление находится в некоторой функции или в main ()?

, и скажем, у меня также есть эти командные строки:

arr[0] = new String("abc");
arr[1] = new List();

, где arr[0] и arr[1]хранится?

Ответы [ 4 ]

13 голосов
/ 10 августа 2011

Диаграмма памяти:

Memory diagram

Ящики - это ячейки памяти (в которых можно хранить двоичные числа).
Стрелки - это ссылки на память (то есть указатели).

8 голосов
/ 10 августа 2011

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

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

Так, например, следующим объектам выделены отдельные области памяти, выделенные для них в куче:

new Object[20]
new String("abc")
new List() // This contains a reference to an initial array, which is also on the heap.

Обратите внимание, что естьочень редко, когда new String("abc") предпочтительнее "abc", так как строковые литералы все равно будут существовать в памяти пакета, а строки неизменяемы.Нет смысла выделять дополнительную память для точной копии строки, которая уже существует в памяти.

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

5 голосов
/ 10 августа 2011

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

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

Так, например:

                                    // This array object is
                                    // stored on the heap.
String[] arr                      = new String[5];
// This reference (arr) is stored
// in a variable on the stack.

В случае массива ссылочных типов, таких как Object[], выделенное пространство представляет собой непрерывный блок, достаточно большой для хранения скольких ссылок , которые будет содержать массив. Любая конкретная ссылка, такая как ссылка на arr[0], сама будет указывать на другое место в куче, где хранится отдельный объект.

The array, somewhere on the heap:
[a*][b*][  ][  ][  ]

a (elsewhere on the heap):
"abc"

b (yet another heap location):
[A List object]

Единственное исключение - это массивы примитивов, например int[]: в этом случае сам массив все еще является непрерывным блоком в куче, но каждая позиция в массиве содержит собственно фактическое значение, а не ссылку на другая позиция в куче.

0 голосов
/ 10 августа 2011

Массив n Строки -

  • Последующий список n ссылок на объекты в куче
  • n одиночные строковые объекты со ссылкой на массив в куче
  • n массивы символов в куче

Этот массив также имеет ссылку, которую можно хранить в стеке или (как поле в классе) в куче

...