Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/google-cloud-platform/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java中盒装原语的存储成本是多少?_Java_Memory_Primitive_Jvm Hotspot - Fatal编程技术网

Java中盒装原语的存储成本是多少?

Java中盒装原语的存储成本是多少?,java,memory,primitive,jvm-hotspot,Java,Memory,Primitive,Jvm Hotspot,像java中的java.lang.Integer或java.lang.Character这样的装箱原语有多大(以字节为单位) 一个int是4个字节,一个典型的指针也是4个字节(如果没有被JVM压缩)。整数(无缓存)的成本是否因此4字节+4字节=8字节?box对象中是否还有其他隐藏字段或对象相关的额外开销(即,是否存在我不知道的对象的一般成本?) 我对缓存问题不感兴趣。我知道JVM缓存了一定范围内的整数 我们可以重新表述这个问题:与原始值相比,盒装值所用内存量的最大乘数是多少 编辑:我知道JVM存

像java中的
java.lang.Integer
java.lang.Character
这样的装箱原语有多大(以字节为单位)

一个
int
是4个字节,一个典型的指针也是4个字节(如果没有被JVM压缩)。整数(无缓存)的成本是否因此
4字节+4字节=8字节
?box对象中是否还有其他隐藏字段或对象相关的额外开销(即,是否存在我不知道的对象的一般成本?)

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

我们可以重新表述这个问题:与原始值相比,盒装值所用内存量的最大乘数是多少

编辑:我知道JVM存在多种实现。典型的32位热点实现的典型成本是多少?

不止这些

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

也似乎存在VM实现差异。确定这一点的最佳方法是在剖析器中将其拉上来

我(超级棒)的估计是。 对象引用16字节(64位JVM) 类引用16字节 原语值4字节(假定为int.) 全部的36字节


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

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

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

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

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

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


引用的大小显然不会影响对象本身的大小,除非它引用了其他对象,而对于简单的int包装器来说,情况并非如此。如果可以的话,32位的每个引用有4字节,堆的每个引用有4字节我知道这并不能完全回答您关于盒装原语存储成本的问题,但我从您的问题中感觉到,您正在质疑您是否有权使用它们

以下是约书亚·布洛赫(Joshua Bloch)从《有效Java》(第二版)中摘录的一段内容,它将帮助您做出以下决定:

“那么什么时候应该使用盒装原语呢?它们有几种合法的用途
第一种是作为集合中的元素、键和值。您不能将基本体放入集合中,因此必须使用装箱基本体。这是一种更一般的特殊情况。您必须在参数化类型中使用装箱基本体作为类型参数(第5章),因为该语言不允许您使用原语。例如,您不能将变量声明为Thread-Local类型,因此必须使用ThreadLocal。最后,在进行反射方法调用时,必须使用装箱原语(第53项)。

总之,只要您有选择,就优先使用基本体而不是盒装基本体。基本体类型更简单、更快。如果必须使用盒装基本体,请小心!自动装箱可以减少使用盒装基本体的冗长性,但不会减少危险。当您的程序将两个盒装基本体与==运算符进行比较时,它会执行i身份比较,这几乎肯定不是您想要的。当您的程序执行包含已装箱和未装箱原语的混合类型计算时,它会执行取消装箱,当您的程序执行取消装箱时,它会抛出NullPointerException。最后,当您的程序装箱原语值时,可能会导致成本高昂且不必要的对象创建ns.“


希望有帮助

对于这些答案,有一个非常小的补充,即盒装原语会发生一些重复数据消除。例如,
Integer::valueOf(int)
使用
java.lang.IntegerCache
,它使用的整数实例的值范围为
-128..127
。因此,您已经提到了装箱对象的大小,但并不是每个对象都是单独的对象。

从某种角度来看,这个问题是无法回答的,因为装箱原语的开销没有在任何规范中指定。它可以而且将因VM和平台而异。带有标记内存的硬件平台甚至可能没有开销。重复的。我认为这也可能取决于您使用的装箱整数的上下文以及运行时编译器正在进行的任何优化。另请参阅,我对您如何得出这些数字一点也不了解。。在
oop.hpp
中查看我的热点源代码,为了完整性起见,这也让我一点也不明智(我只能在那里找到通常的两个指针):如果对象是同步的,则会有一个本机结构保存互斥体。@bestsss Right,完全忽略了这一点。我认为只有当我们有一个争用锁(假设有偏锁)时,才会创建重量级锁。如果我们不这样做,也不使用对象的哈希代码,我认为Hotspot会将tid存储在对象头本身中。因此,仅仅调用
synchronized(foo)
不一定会分配任何内存。是的。如果存在System.identityHashCode()请求,则无争用偏向锁不会膨胀标头。后者(非官方)用于防止对选定对象进行有偏锁定。(我的意思是大部分内容都很满足->有时我使用
objectlock=newbyte(1)
来简化序列化