Шаги в процессе выделения памяти для объектов Java - PullRequest
12 голосов
/ 26 ноября 2008

Что происходит в памяти, когда класс создает следующий объект?

public class SomeObject{

    private String strSomeProperty;

    public SomeObject(String strSomeProperty){
        this.strSomeProperty = strSomeProperty;
    }
    public void setSomeProperty(String strSomeProperty){
        this.strSomeProperty = strSomeProperty;
    }
    public String getSomeProperty(){
        return this.strSomeProperty;
    }
}

В классе SomeClass1:

SomeObject so1 = new SomeObject("some property value");

В классе SomeClass2:

SomeObject so2 = new SomeObject("another property value");

Как выделяется память для нового экземпляра объекта и его свойств?

Ответы [ 3 ]

12 голосов
/ 26 ноября 2008

Давайте пройдем через это:

SomeObject so1 = new SomeObject("some property value");

... на самом деле сложнее, чем кажется, потому что вы создаете новую строку. Это может быть проще думать как:

String tmp = new String("some property value");
SomeObject so1 = new SomeObject(tmp);
// Not that you would normally write it in this way.

(Чтобы быть абсолютно точным - это не совсем эквивалентно. В оригинале «новая строка» создается во время компиляции и является частью образа .class. Вы можете думать об этом как о хаке производительности.)

Итак, сначала JVM выделяет место для строки. Обычно вы не знаете или не заботитесь о внутренних элементах реализации String, поэтому просто верьте, что кусок памяти используется для представления «некоторого значения свойства». Кроме того, у вас временно выделена память, содержащая ссылку на строку. Во второй форме он явно называется tmp; в исходном виде Java обрабатывает его, не называя его.

Затем JVM выделяет пространство для нового SomeObject. Это немного места для внутренней бухгалтерии Java и места для каждого из полей объекта. В этом случае есть только одно поле, strSomeProperty.

Помните, что strSomeProperty это просто ссылка на строку. Пока что он будет инициализирован нулем.

Далее конструктор выполняется.

this.strSomeProperty = strSomeProperty;

Все, что для этого нужно - скопировать ссылку в строку в ваше поле strSomeProperty.

Наконец, место выделено для ссылки на объект so1. Это устанавливается со ссылкой на SomeObject.

so2 работает точно так же.

7 голосов
/ 26 ноября 2008

Определение использования памяти в Java Д-р Хайнц М. Кабуц дает точный ответ, плюс программа для расчета использования памяти. Соответствующая часть:

  1. Класс занимает не менее 8 байтов. Итак, если вы говорите, новый Object (); Вы выделите 8 байтов в куче.
  2. Каждый элемент данных занимает 4 байта, кроме длинных и двойных, которые занимают 8 байтов. Даже если элемент данных является байтом, он все равно займет 4 байта! Кроме того, объем используемой памяти увеличивается в 8-байтовых блоках. Итак, если у вас есть класс, который содержит один байт, он займет 8 байтов для класса и 8 байтов для данных, всего 16 байтов (стон!).
  3. Массивы немного умнее. Примитивы упаковываются в массивы, поэтому, если у вас есть массив байтов, каждый из них будет занимать один байт (вау!). Использование памяти, конечно, все еще увеличивается в 8-байтовых блоках.

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

3 голосов
/ 28 августа 2012

Очки для запоминания:

  1. Когда вызывается метод, в верхней части стека создается фрейм.
  2. Как только метод завершил выполнение, поток управления возвращается к вызывающему методу, и соответствующий ему кадр стека сбрасывается.
  3. Локальные переменные создаются в стеке.
  4. Переменные экземпляра создаются в куче и являются частью объекта, которому они принадлежат.
  5. В стеке создаются ссылочные переменные.

Ссылка: http://www.javatutorialhub.com/java-stack-heap.html

...