Подтвердить что ты не робот

Какова стоимость стоимости наследования Java?

Существуют различные статьи на межстранах, которые пытаются эмпирически оценить накладные расходы java.lang.Object, в частности, реализаций JVM. Например, я видел накладные расходы на размер голой Object оценивается в 8 байт в некоторых JVM.

То, что я хотел бы знать, заключается в том, представляет ли типичная реализация JVM отношения extends инкрементный размер накладных расходов на каждом уровне иерархии классов. Другими словами, предположим, что у вас есть иерархия классов с N уровнями подклассов. Являются ли накладные расходы встроенным представлением экземпляра класса O (1) или O (N)?

Я полагаю, что это O (1), потому что, хотя размер некоторых скрытых пушистых вещей, которые вы должны быть Java Object (vtable, цепочка классов), будет возрастать по мере роста иерархии наследования, класс, а не на экземпляр, а реализация JVM может хранить указатели постоянного размера для этих объектов в заголовке с постоянным размером, прикрепленном к каждому Object.

Итак, теоретически, служебные данные, непосредственно связанные с представлением в памяти любого объекта Java, должны быть O (1) для глубины наследования N. Кто-нибудь знает, действительно ли это на практике?

4b9b3361

Ответ 1

Если вы сомневаетесь, посмотрите источник (ну, источник, каждый JVM может выбрать, как это сделать, в качестве стандартного не предусматривает какого-либо внутреннего представительства). Итак, я посмотрел и нашел следующий комментарий в реализации JVK 7-u60 hotspot JVM:

// A Klass is the part of the klassOop that provides:
//  1: language level class object (method dictionary etc.)
//  2: provide vm dispatch behavior for the object
// Both functions are combined into one C++ class. The toplevel class "Klass"
// implements purpose 1 whereas all subclasses provide extra virtual functions
// for purpose 2.

// One reason for the oop/klass dichotomy in the implementation is
// that we don't want a C++ vtbl pointer in every object.  Thus,
// normal oops don't have any virtual functions.  Instead, they
// forward all "virtual" functions to their klass, which does have
// a vtbl and does the C++ dispatch depending on the object's

Как я его читаю, это означает, что для этой (очень популярной) реализации экземпляры объектов хранят только указатель на свой класс. Стоимость для каждого экземпляра класса этого класса, имеющего более длинную или более короткую цепочку наследования, фактически равна 0. Сами классы занимают место в памяти, хотя (но только один раз для каждого класса). Эффективность времени выполнения цепей глубокого наследования - это еще одно дело.

Ответ 2

Состояние спецификации JVM

Виртуальная машина Java не предусматривает каких-либо конкретных внутренних структура объектов.

Таким образом, спецификация не волнует, как вы это делаете. Но...

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

Таким образом, в типичных реализациях Oracle для методов используется O (1). Эта таблица методов - это Область метода, которая соответствует классу.

Виртуальная машина Java имеет область методов, которая является общей для всех Темы виртуальной машины Java. Область метода аналогична область хранения для скомпилированного кода обычного языка или аналогичного к сегменту "текст" в процессе операционной системы. Он хранит структуры каждого класса, такие как пул постоянной времени выполнения, поле и данные метода и код для методов и конструкторов, включая специальные методы (§2.9), используемые в инициализации класса и экземпляра и инициализация интерфейса.

Кроме того, около записей метода

Структуры method_info представляют все методы, объявленные этим класс или тип интерфейса, включая методы экземпляра, методы класса, методы инициализации экземпляра (§2.9) и любой класс или интерфейс метод инициализации (§2.9). Таблица методов не включает элементы представляющие методы, которые унаследованы от суперклассов или суперинтерфейсы.

Ответ 3

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

  • поля экземпляра класса и его родительских классов, которые, как я полагаю, вы не хотите включать в термин "служебные данные"
  • некоторые средства для блокировки объекта
  • если сборщик мусора перемещает объекты, тогда некоторые средства для записи исходного хэша объекта (для Object.hashCode)
  • некоторые средства доступа к информации о типе

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

То есть добавление лишних пустых классов или интерфейсов в класс не должно увеличивать размер его экземпляров. Я не думаю, что либо язык, либо спецификация JVM действительно гарантируют это, однако, поэтому не делайте слишком много предположений о том, что разрешено выполнять "ненормальную" реализацию Java.

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

Ответ 4

Double и Integer, которые расширяют Number, который расширяет Object, не имеют поведения O (n), то есть Integer не является 3X размером объекта, поэтому я считаю, что ответ O (1). например см. этот старый вопрос SO

Ответ 5

в теории, служебные данные, непосредственно связанные с представлением в памяти любого объекта Java, должны быть O (1) для глубины наследования N. Кто-нибудь знает, действительно ли это на практике?

Это не может быть O (1), если на каждом уровне нет нулевых экземпляров. Каждому члену экземпляра требуется пространство на каждый экземпляр.