Какова стоимость хранения коробочного примитива в Java? - PullRequest
13 голосов
/ 27 января 2012

Какой размер в байтах представляет собой коробочный примитив, такой как java.lang.Integer или java.lang.Character в Java?

int равен 4 байта, типичный указатель также 4 байта (если он не сжатJVM).Таким образом, стоимость целого числа (без кеширования) составляет 4 bytes + 4 bytes = 8 bytes?Существуют ли еще скрытые поля внутри объекта-бокса или дополнительные накладные расходы, связанные с объектами (т. Е. Существуют ли общие затраты для объектов, о которых я не знаю?).

Меня не интересуют проблемы с кэшированием,Я знаю, что целые числа в определенном диапазоне кэшируются JVM.

Можно перефразировать вопрос: какой максимальный коэффициент умножается на объем памяти, используемый для значений в штучной упаковке по сравнению с примитивными значениями?

РЕДАКТИРОВАТЬ: Я понимаю, что существует несколько реализаций JVM.Какова типичная стоимость в типичной 32-битной реализации HotSpot?

Ответы [ 3 ]

7 голосов
/ 27 января 2012

Это определяется реализацией, поэтому конкретного ответа нет. Но я должен быть в состоянии ответить на это для Hotspot.

Что вам нужно знать, так это: Hotspot всегда выравнивает объекты по 8-байтовым границам. Кроме того, есть 2 слова для каждого объекта. [1]

Если мы сложим это вместе, мы получим:

32-битная ВМ: 4-байтовое целое число + 2 слова заголовка объекта = 12 байт. Это не кратно 8, поэтому в результате стоимость одного целого числа будет следующим кратным 8: 16 байт.

64-битная ВМ: 4-байтовое целое число + 2 слова = 20 байт. Снова округление: размер 24 байта.

Размер ссылки, очевидно, не влияет на размер самого объекта, за исключением случаев, когда он имеет ссылки на другие объекты, что не относится к простой оболочке типа int. Если бы это было так, у нас было бы 4 байта на ссылку для 32-битных и 4 байта для куч <= 32 ГБ с <code>CompressedOops на современных JVM (в противном случае 8 байтов) для 64-битных JVM.

[1] Заинтересованные люди могут посмотреть код в share/vm/oops/oop.hpp

1 голос
/ 27 января 2012

Это нечто большее.

У каждой ссылки на объект есть дополнительные издержки, такие как ссылка на класс. Мало того, ваш 4-байтовый указатель не совсем точен. Это ссылка, так что это идентификатор плюс указатель, И этот указатель может быть 8 байтов, если вы используете 64-битную JVM.

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

Моя оценка (Super SWAG) будет. Ссылка на объект 16 байтов (64-битная JVM) Ссылка на класс 16 байтов примитивное значение 4 байта (при условии int.) Всего. 36 байт.

РЕДАКТИРОВАТЬ: Теперь, когда вы указали 32-битную JVM, моя SWAG была бы 20 байтов, используя ту же математику выше.

0 голосов
/ 27 января 2012

Я знаю, что это не совсем отвечает на ваш вопрос о стоимости хранения примитивов в штучной упаковке, но я чувствую из вашего вопроса, что вы спрашиваете, оправдано ли их использование.

Вот выдержка из книги «Эффективная Java (2-е издание)» Джошуа Блоха, которая должна помочь вам принять решение:

"So when should you use boxed primitives? They have several legitimate uses. The first is as elements, keys, and values in collections. You can’t put primitives in collections, so you’re forced to use boxed primitives. This is a special case of a more general one. You must use boxed primitives as type parameters in parame- terized types (Chapter 5), because the language does not permit you to use primi- tives. For example, you cannot declare a variable to be of type Thread- Local<int>, so you must use ThreadLocal<Integer> instead. Finally, you must use boxed primitives when making reflective method invocations (Item 53).

In summary, use primitives in preference to boxed primitives whenever you have the choice. Primitive types are simpler and faster. If you must use boxed primitives, be careful! Autoboxing reduces the verbosity, but not the danger, of using boxed primitives. When your program compares two boxed primitives with the == operator, it does an identity comparison, which is almost certainly not what you want. When your program does mixed-type computations involving boxed and unboxed primitives, it does unboxing, and when your program does unboxing, it can throw a NullPointerException. Finally, when your program boxes primitive values, it can result in costly and unnecessary object creations."

Надеюсь, это поможет.

...