Что определяет размер объекта Java? - PullRequest
40 голосов
/ 15 августа 2011

Что влияет на размер одного объекта в памяти?

Я знаю, что примитивы и ссылки будут, но есть ли что-нибудь еще? Будет ли иметь значение количество методов и их длина?

Ответы [ 4 ]

65 голосов
/ 15 августа 2011

Это полностью зависит от реализации, но есть несколько факторов, которые влияют на размер объекта в Java.

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

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

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

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

В дополнение к полям и методам,Многие другие факторы могут повлиять на размер объекта.Вот некоторые из них:

В зависимости от того, какой тип сборщика мусора (или сборщиков) использует JVM, у каждого объекта может быть дополнительное пространство для хранения информации о том, является ли объект живым, мертвым, достижимым и т. Д.Это может увеличить пространство для хранения, но это вне вашего контроля.В некоторых случаях JVM может оптимизировать размеры объектов, пытаясь сохранить объект в стеке вместо кучи.В этом случае накладные расходы могут даже не присутствовать для некоторых типов объектов.

Если вы используете синхронизацию, для объекта может быть выделено дополнительное пространство, чтобы его можно было синхронизировать.Некоторые реализации JVM не создают монитор для объекта до тех пор, пока он не понадобится, поэтому вы можете получить объекты меньшего размера, если не используете синхронизацию, но не можете гарантировать, что это будет так.

Кроме того, для поддержки таких операторов, как instanceof и приведение типов, каждому объекту может быть выделено некоторое пространство для хранения информации о типе.Как правило, это связано с vtable объекта, но нет гарантии, что это будет верно.

Если вы используете утверждения, некоторые реализации JVM создадут в вашем классе поле, содержащее, включены ли утверждения.Затем он используется для отключения или включения утверждений во время выполнения.Опять же, это зависит от реализации, но это хорошо иметь в виду.

Если ваш класс является нестатическим внутренним классом, ему может понадобиться ссылка на содержащий его класс, чтобы он мог получить доступ к егополя.Однако JVM может оптимизировать это, если вы никогда не будете использовать это.

Если вы используете анонимный внутренний класс, классу может понадобиться дополнительное место, зарезервированное для хранения переменных final, которые видны в пределах области его охвата, чтобы на них можно было ссылаться внутри класса.Это зависит от реализации, копируется ли эта информация в поля класса или просто сохраняется локально в стеке, но это может увеличить размер объекта.

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

7 голосов
/ 15 августа 2011

Чтобы добавить немного (по общему мнению, неопределенных) данных в отличный ответ @ templatetypedef.Эти числа для типичных недавних 32-битных JVM, но они специфичны для реализации :

  • Заголовок заголовка для каждого объекта обычно 2 словадля обычного объекта и 3 слова для массива.Заголовок включает в себя связанные с GC флаги и некоторый указатель на фактический класс объекта.Для массива требуется дополнительное слово для хранения размера массива.

  • Если вы вызвали (прямо или косвенно) System.identityHashCode() для объекта, и он пережил GCцикл, затем добавьте дополнительное слово для хранения значения хэш-кода.(Современные JVM используют хитрый трюк, чтобы избежать резервирования поля заголовка хеш-кода для всех объектов ...)

  • Степень детализации выделения памяти может быть несколько слов;например, 2.

  • Поля объекта обычно выровнены по словам;т.е. они не упакованы.

  • Элементы массива примитивного типа упакованы, но логические значения обычно представлены байтом в упакованном виде.

  • Ссылки занимают 4 байта как поля, так и элементы массива.

Ситуация немного сложнее для 64-разрядных JVM из-за сжатия указателей (OOPS) в некоторых JVM.Кроме того, я не уверен, совпадают ли поля 32 или 64 бита.


(Примечание: вышеизложенное основано на том, что я слышал / читал в разных местах от разных "знающих людей".не является окончательным источником информации такого рода, кроме Oracle / Sun, и (AFAIK) они ничего не опубликовали.)

4 голосов
/ 15 августа 2011

Проверьте java.sizeOf в sourceforge здесь: http://sizeof.sourceforge.net/

0 голосов
/ 15 августа 2011

AFAIK, в исходном коде HBase есть некоторая рассылка о размере объекта, основанная на некоторых общих известных правилах того, как разные поля занимают пробелы.И это будет отличаться в 32-битной или 64-битной ОС.По крайней мере, выше людей все знают.Но я не стал вдаваться в подробности, почему они это делают.Но они действительно сделали это в исходном коде.

Кроме того, класс Java.lang.intrument.Intrumentation может сделать это также с помощью getObjectSize ().Я предполагаю, что проект с открытым исходным кодом также основан на этом.В этой ссылке есть детали того, как его использовать. Как лучше всего определить размер объекта в Java?

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...