Почему накладные расходы при размещении объектов / массивов в Java?

9

Сколько байтов массив занимает в Java? Предположим, что это 64-битная машина, а также предположим, что в массиве есть N элементов, поэтому все эти элементы занимают 2 * N, 4 * N или 8 * N байт для разных типов массива.

И лекция в Coursera говорит, что она будет занимать 2 * N + 24, 4 * N + 24 или 8 * N + 24 байта для массива N элементов, а 24 байта называются издержками, но не объясняет, почему накладные расходы необходимо.

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

Что именно это накладные расходы? Из чего состоят эти 24/16 байтов?

Кроме того, эти накладные расходы существуют только в Java? Как насчет C, C ++ и Python?

Gnijuohz
источник
2
Выезд: stackoverflow.com/a/258150/1029272
Деку
1
@Gnijuohz: Вы хотите спросить: из каких данных состоят эти накладные расходы?
FrustratedWithFormsDesigner
@YannisRizos: Я думаю, что ОП хочет знать, что на самом деле в этих 24 байтах, для массивов.
FrustratedWithFormsDesigner
@FrustratedWithFormsDesigner Ах, похоже, это лучшая интерпретация вопроса, чем моя.
Яннис
@YannisRizos извините за мое плохое отношение. Но когда вы публикуете эту ссылку, я не могу не думать, что это какой-то сарказм. Слишком оборонительный, я думаю.
Gnijuohz

Ответы:

16

Каждый объект Java имеет заголовок, который содержит информацию, важную для JVM. Наиболее важной является ссылка на класс объекта (одно машинное слово), и есть некоторые флаги, используемые сборщиком мусора и для управления синхронизацией (поскольку каждый объект может быть синхронизирован), который принимает другое машинное слово (использование частичных слов будет плохо для производительности). Таким образом, это 2 слова, что составляет 8 байтов в 32-битных системах и 16 байтов в 64-битных. Массивам дополнительно требуется поле int для длины массива, которая составляет еще 4 байта, возможно, 8 в 64-битных системах.

Что касается других языков:

  • C не имеет объектов, поэтому, конечно, он не имеет заголовков объектов - но может иметь заголовок на каждом отдельно выделенном фрагменте памяти.

  • В C ++ у вас нет сборщика мусора и вы не можете использовать произвольные объекты для синхронизации, но если у вас есть классы с переопределенными методами, каждый объект имеет указатель на свою vtable, так же как ссылка объекта Java на свой класс. Если вы используете умные указатели, которые выполняют сбор мусора, им нужны служебные данные.

  • Я не знаю насчет Python, но я почти уверен, что для него нужна ссылка на класс и служебная информация для сборщика мусора.

Майкл Боргвардт
источник
В настоящее время в OpenJDK идет работа по уменьшению размера заголовков объектов, небольшие, но важные шаги :-)
Мартейн Вербург
В C ++ только полиморфные классы нуждаются в vtables. std::pair<int, float>это простой класс, который вообще не нуждается в vtable. В результате он может очень хорошо уместиться в 8 байтов. Кроме того, умные указатели на самом деле не нужно добавлять уборку. Яркий контр-пример std::unique_ptr<T>, который, как правило, такой же большой, как необработанный T*(unique_ptr, конечно, не делает GC).
MSalters
4
C также имеет накладные расходы, каждый mallocвыделенный блок памяти нуждается в заголовке, который freeзатем использует.
Herby
По крайней мере, одна библиотека malloc, о которой я знаю, использует 8-байтовый заголовок в 32-битных системах (длина 4-байта заключена в скобки двумя наборами 2-байтовых значений дозорных, IIRC).
Donal Fellows