2012-01-27 2 views
10

Насколько велика, в байтах, примитив в штучной упаковке, такой как java.lang.Integer или java.lang.Character в Java?Какова стоимость хранения примитива в штучной упаковке в Java?

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

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

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

EDIT: Я понимаю, что существует множество реализаций JVM. Какова типичная стоимость типичной 32-битной реализации HotSpot?

+7

С определенной точки зрения этот вопрос невозможен, поскольку накладные расходы на примитиве в штучной упаковке не указаны в какой-либо спецификации. Он может и будет варьироваться от VM до VM и платформы к платформе. Аппаратная платформа с помеченной памятью может иметь нулевые накладные расходы. –

+0

дубликат [В Java, что является лучшим способом определения размера объекта?] (Http://stackoverflow.com/questions/52353/in-java-what-is-the-best-way-to- определение-в-размер-о-объекта). – DwB

+0

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

ответ

5

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

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

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

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

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

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

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

+1

ради полноты: если объект синхронизирован, будет создана нативная структура, содержащая мьютекс. – bestsss

+0

@bestsss Право, полностью игнорировал это. Я думаю, что супертяжелые блокировки создаются только в том случае, если у нас есть фиксированная блокировка (предполагая смещенную блокировку). Если мы этого не сделаем и не будем использовать хэш-код объекта, я думаю, что Hotspot хранит tid в самом заголовке объекта. Поэтому просто вызов 'synchronized (foo)' может не обязательно выделять какую-либо память. – Voo

+0

есть. незащищенные смещенные блокировки не раздувают заголовок, если есть запрос System.identityHashCode(). Последний используется (unofficiallY) для предотвращения смещенной блокировки на выбранном объекте. (я имею в виду, в основном, контент -> иногда я использовал 'Object lock = new Byte (1)' для упрощения сериализации – bestsss

1

Это больше, чем это.

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

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

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

EDIT: Теперь, когда вы укажете 32-битную JVM, мой SWAG будет 20 байтов, используя ту же математику выше.

+0

У меня нет ни малейшего представления о том, как вы придумываете эти цифры. глядя на мой источник Hotspot в 'oop.hpp' также делает я не мудрее (я могу найти только обычные 2 указателя) – Voo

0

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

Вот отрывок из Effective Java (второе издание) Джошуа Блох, которые должны помочь вам решить:

"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."

Надежда, что помогает.

Смежные вопросы