17

java.lang.Integer像 Java或Java中的盒装原语有多大(以字节为单位)java.lang.Character

anint是 4 个字节,一个典型的指针也是 4 个字节(如果没有被 JVM 压缩)。整数(没有缓存)的成本是这样的4 bytes + 4 bytes = 8 bytes吗?盒子对象中是否有更多隐藏字段或与对象相关的额外开销(即我不知道的对象是否有一般成本?)。

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

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

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

4

4 回答 4

9

这是实现定义的,所以没有具体的答案。但我应该能够为热点回答这个问题。

你需要知道的是:Hotspot 总是在 8 字节边界上对齐对象。此外,每个对象都有 2 个单词开销。[1]

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

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

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

引用的大小显然不会影响对象本身的大小,除非它具有对其他对象的引用,而简单的 int 包装器则不是这种情况。CompressedOops如果可以的话,对于 64 位 JVM,在现代 JVM 上(否则为 8字节),对于 32 位和 4 字节的堆 <= 32gb,我们将有 4 字节的引用。

[1] 有兴趣的可以看里面的代码share/vm/oops/oop.hpp

于 2012-01-27T17:55:59.040 回答
1

不仅如此。

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

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

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

编辑:既然您指定了 32 位 JVM,我的 SWAG 将是 20 字节,使用上述相同的数学。

于 2012-01-27T17:38:52.123 回答
0

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

这是 Joshua Bloch 的 Effective Java (2nd Edition) 的摘录,它应该可以帮助您做出决定:

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

希望有帮助。

于 2012-01-27T18:03:30.053 回答
0

这些答案的一个非常小的补充是盒装原语发生了一些重复数据删除。例如,Integer::valueOf(int)使用java.lang.IntegerCacheInteger 实例且值在 range 中的用途-128..127。所以,你有上面提到的盒装对象的大小,但并不是每个都是单独的对象。

于 2019-09-13T16:37:54.570 回答