Что происходит в памяти, когда класс создает экземпляр следующего объекта?
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");
Как выделена память для вновь созданного объекта и его свойств?
Ответ 1
Пусть пройдет через него:
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. Обычно вы не знаете или не заботитесь о внутренних функциях реализации String, поэтому просто доверьтесь, что кусок памяти используется для представления "некоторого значения свойства". Кроме того, у вас есть временная выделенная память, содержащая ссылку на String. Во второй форме он явно называется tmp
; в вашей первоначальной форме Java обрабатывает его, не называя его.
Далее JVM выделяет пространство для нового SomeObject. Это немного пространства для внутренней бухгалтерии Java и пространства для каждого из полей объекта. В этом случае есть только одно поле, strSomeProperty
.
Имейте в виду, что strSomeProperty
- это просто ссылка на String. Пока что он будет инициализирован нулевым.
Затем выполняется конструктор.
this.strSomeProperty = strSomeProperty;
Все это делает копию ссылки на строку в поле strSomeProperty
.
Наконец, пространство присваивается для ссылки на объект so1
. Это задается ссылкой на SomeObject.
so2
работает точно так же.
Ответ 2
Определение использования памяти в Java доктора Хайнца М. Кабуца дает точный ответ, а также программу для расчета использования памяти. Соответствующая часть:
- Класс занимает не менее 8 байт. Итак, если вы скажете новый Object(); вы выберете 8 байтов в куче.
- Каждый элемент данных занимает 4 байта, за исключением длинного и двойного, которые занимают 8 байтов. Даже если элемент данных является байтом, он все равно занимает 4 байта! Кроме того, объем используемой памяти увеличивается в 8 байтовых блоках. Итак, если у вас есть класс, содержащий один байт, для этого класса будет 8 байтов и 8 байтов для данных, всего 16 байт (стон!).
- Массивы немного умнее. Примитивы получаются в массивах, поэтому, если у вас есть массив байтов, каждый из них будет принимать один байт (ничего себе!). Использование памяти, конечно же, продолжается в 8-байтовых блоках.
Как отмечают люди в комментариях, строки являются особым случаем, потому что они могут быть интернированы. Вы можете рассуждать о пространстве, которое они занимают таким же образом, но имейте в виду, что то, что выглядит как несколько копий одной и той же строки, может фактически указывать на одну и ту же ссылку.
Ответ 3
Баллы для запоминания:
- Когда вызывается метод, в верхней части стека создается кадр.
- Как только метод завершил выполнение, поток управления возвращается к вызывающему методу, и его соответствующий стек стека очищается.
- Локальные переменные создаются в стеке.
- Переменные экземпляра создаются в куче и являются частью объекта, к которому они принадлежат.
- В стеке создаются ссылочные переменные.
Ссылка: http://www.javatutorialhub.com/java-stack-heap.html