Java - Нулевая переменная требует пространства в памяти
class CheckStore {
private String displayText;
private boolean state;
private String meaningfulText;
private URL url;
public CheckStore(String text, boolean state) {
this.displayText = text;
this.state = state;
}
:
:
}
Поскольку я инициализирую в конструкторе только две переменные (displayText
и state
), оставшиеся две переменные (meaningfulText
и url
, которые будут иметь значение null
), потребуют пространства в памяти для сохранения значения null
.
Q1. Думаю, им потребуется пространство. Если да, то сколько памяти занимает значение null
в памяти (например, int
занимает 4 байта).
Q2. Сколько пространства занимает строка в памяти. Думаю, это будет зависеть от длины строки. Итак, сколько места занимает строка, сколько длины?
Ответы
Ответ 1
В Java null
- это просто значение, которое может иметь ссылка (которая в основном ограничена указателем). Это означает, что ссылка ссылается на ничего. В этом случае вы все еще занимаете пространство для ссылки. Это 4 байта в 32-битных системах или 8 байтах в 64-битных системах. Однако вы не занимаете места для класса, на который ссылается ссылка, пока вы фактически не выделите экземпляр этого класса для указания ссылки.
Изменить. Что касается String, a String
в Java занимает 16 бит (2 байта) для каждого символа, а также небольшую часть служебных данных, которые, вероятно, недокументированы и специфичны для реализации.
Ответ 2
Я бы хотел добавить:
- переменная ссылочного типа будет инициализирована как нулевое значение.
- null не является объектом. потому что (null instanceof Object) равен false
-
в JVM имеется только одно значение null. Независимо от того, сколько переменных ссылается на null.
Объект s = (String) null;
Объект я = (целочисленный) null;
System.out.println(s == i);//true
Ответ 3
Вы можете использовать jol, чтобы получить макет этого класса. (Однако будьте осторожны, вам может потребоваться более глубокое понимание механики позади него, не слепо доверять результату и быть в курсе, что это всего лишь оценка для используемой в настоящее время виртуальной машины (1.7.0_76 x64 выигрыш в моем случае:):
Я использую версию CLI. Я полагаю, что правильным методом будет включение библиотеки в ваш проект, но в любом случае, похоже, она работает следующим образом:
test>java -cp target\classes;jol-cli-0.3.1-full.jar org.openjdk.jol.Main internals test.CheckStore
Running 64-bit HotSpot VM.
Using compressed oop with 0-bit shift.
Using compressed klass with 0-bit shift.
Objects are 8 bytes aligned.
Field sizes by type: 4, 1, 1, 2, 2, 4, 4, 8, 8 [bytes]
Array element sizes: 4, 1, 1, 2, 2, 4, 4, 8, 8 [bytes]
VM fails to invoke the default constructor, falling back to class-only introspection.
test.CheckStore object internals:
OFFSET SIZE TYPE DESCRIPTION VALUE
0 12 (object header) N/A
12 1 boolean CheckStore.state N/A
13 3 (alignment/padding gap) N/A
16 4 String CheckStore.displayText N/A
20 4 String CheckStore.meaningfulText N/A
24 4 URL CheckStore.url N/A
28 4 (loss due to the next object alignment)
Instance size: 32 bytes (estimated, the sample instance is not available)
Space losses: 3 bytes internal + 4 bytes external = 7 bytes total
и то же самое с автоматическим сжатием oops off:
test>java -XX:-UseCompressedOops -cp target\classes;jol-cli-0.3.1-full.jar org.openjdk.jol.Main internals test.CheckStore
Running 64-bit HotSpot VM.
Objects are 8 bytes aligned.
Field sizes by type: 8, 1, 1, 2, 2, 4, 4, 8, 8 [bytes]
Array element sizes: 8, 1, 1, 2, 2, 4, 4, 8, 8 [bytes]
VM fails to invoke the default constructor, falling back to class-only introspection.
test.CheckStore object internals:
OFFSET SIZE TYPE DESCRIPTION VALUE
0 16 (object header) N/A
16 1 boolean CheckStore.state N/A
17 7 (alignment/padding gap) N/A
24 8 String CheckStore.displayText N/A
32 8 String CheckStore.meaningfulText N/A
40 8 URL CheckStore.url N/A
Instance size: 48 bytes (estimated, the sample instance is not available)
Space losses: 7 bytes internal + 0 bytes external = 7 bytes total
Это только макеты для самого объекта, если ваши поля имеют нулевое значение, тогда он не будет указывать на большее количество объектов, в противном случае вы должны посмотреть на целевые типы (URL
и String
). (И если у вас есть несколько экземпляров всех из них, это зависит, если вы используете одни и те же несколько раз или разные). Пустое поле не может быть пропущено в памяти, так как это потребует изменения размера экземпляра при его назначении. Итак, все поля предварительно сконструированы, они просто не ссылаются на выделенные объекты где-то еще на куче.
NB: вы получите более подробную информацию, если вы реализуете конструктор по умолчанию, но размер в этом конкретном случае будет таким же. В случае, если вы задаетесь вопросом, откуда идет последовательность и заполнение полей, вы можете проверить эту статью - (в основном он выравнивает объекты по 8 байтам, сортирует поля по размеру, группы одного типа вместе, ссылки последние. Сначала поля из супер-типов, выровнены по 4 байт.)