繁体   English   中英

Java中盒装基元的存储成本是多少?

[英]What is the storage cost for a boxed primitive in Java?

Java中的java.lang.Integerjava.lang.Character这样的盒装原语有多大(以字节为单位)?

int是4个字节,典型的指针也是4个字节(如果没有被JVM压缩)。 整数(没有缓存)的成本是4 bytes + 4 bytes = 8 bytes 盒子对象中是否还有任何隐藏字段或者对象产生的额外开销(即,我不知道对象的一般成本?)。

我对缓存问题不感兴趣。 我知道JVM会缓存某个范围内的整数。

可以重新解释这个问题:用于盒装值与原始值的内存量相乘的最大因子是多少?

编辑:我明白存在JVM的多个实现。 典型的32位HotSpot实现的典型成本是多少?

这是实现定义的,所以没有具体的答案。 但我应该能够为Hotspot回答它。

您需要知道的是:Hotspot始终在8字节边界上对齐对象。 此外,每个对象有2个字开销。 [1]

如果我们把它放在一起,我们得到:

32位VM:4字节整数+ 2字对象标题= 12字节。 这不是8的倍数,因此1个整数的成本是8:16byte的下一个倍数。

64位VM:4字节整数+ 2字= 20字节。 再次向上舍入:24字节大小。

引用的大小显然不会影响对象本身的大小,除非它引用了其他对象,而不是简单的int包装器。 如果是这样的话,对于64位JVM,在现代JVM上使用CompressedOops (否则为8byte),对于32位而言,每个引用有4byte,对于堆<= 32gb,我们有4byte。

[1]感兴趣的人可以查看share/vm/oops/oop.hpp

它不止于此。

每个对象引用都有额外的开销,例如Class引用。 不仅如此,您的4字节指针还不太准确。 它是一个引用,所以它是一个ID加一个指针,如果你在64位JVM上,那么指针可能是8个字节。

似乎还存在VM实现差异。 确保这一点的最好方法是在分析器中将其拉出来。

我的(超级SWAG)估计会是。 对象引用16字节(64位JVM)类引用16字节原始值4字节(假设为int。)总计。 36个字节。

编辑:现在您指定32位JVM我的SWAG将使用上面相同的数学20字节。

这些答案的一个非常小的补充是盒装基元有一些重复数据删除。 例如, Integer::valueOf(int)使用java.lang.IntegerCache ,它使用范围为-128..127值的Integer实例。 因此,对于盒装对象,您有上述尺寸,但并非每个都是单独的对象。

我知道这并没有完全回答你关于盒装基元存储成本的问题,但我从你的问题中感觉到你在质疑你是否有必要使用它们。

以下是Joshua Bloch撰写的Effective 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."

希望有所帮助。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM