繁体   English   中英

在Java中,可变内存空间是动态分配还是静态分配?

[英]in Java is variable memory space allocated dynamically or statically?

如果我们运行这一行代码

long num = 5;

这个变量有64位空间吗? 还是大小取决于旁边的值? 从逻辑上讲,它应为64位,因为原始数据类型是可变的。 但是我的结论是真的吗?

此外,如果我们有一个不变的对象,例如字符串

String str = "Hello World";

默认情况下,将此字符串赋予最大内存似乎很不直观。 如果要设置一个String然后进行更改,则只需将指针更改为第二个String(新创建的String)的内存地址即可。

有人可以回答这个问题或为我指出正确的方向吗?

long是一个64-bit原始值,无论您保留的是什么实际值。

String是包装char[] 内部数组的大小取决于内部字符的数量。 每个char 16-bits ¹。

¹比这复杂一点,但通常来说,每个字符16位。

根据JLS§4.2§4.2.1

整数类型为byte,short,int和long,其值分别为8位,16位,32位和64位有符号的二进制补码整数,以及char,其值为16位无符号整数。代表UTF-16代码单元(第3.1节)。

浮点类型为浮点型,其值包括32位IEEE 754浮点数;以及双精度型,其值包括64位IEEE 754浮点数。

显然,为了使这些原语能够具有最小值和最大值,它们需要用固定数量的内存表示,因此它不能可变。

关于String ,每个对象都有一个char[] (直到JDK 9)支持,该char[]具有固定的长度。

有不同种类的变量,因此,没有一个答案。

堆变量(也称为字段 )通常具有与数据类型匹配的大小,有时甚至更多,具体取决于对齐方式,但始终足以容纳数据类型的任何有效值。 就像您自己已经提到的那样, 引用类型指向堆内存中的一个对象,然后为另一个对象分配引用只会更改地址,因此引用类型的变量具有固定大小,能够存储堆内存地址¹,无论引用对象的大小。 由于String实例是不可变的,因此重新分配是更改String变量的唯一方法。

对于局部变量,情况有所不同。 在这里,处理速度比减少内存消耗更为重要。 因此,数据类型booleanbyteshortcharint都统一视为int ,您已经在源代码级别上注意到了,因为在这些数据类型上进行的所有算术运算( boolean除外)都得出int 这种转换已经在编译时发生。 在运行时优化代码时,JVM可以重新建立较小的存储类型,但这不是通常的方向。 局部变量更有可能映射到CPU寄存器,而根本没有任何存储空间。 或者,如果将寄存器计为存储,则它们的宽度至少为32位,而在当今大多数系统中为64位。

保持你的long num = 5; 例如,像HotSpot这样的JVM使用诸如静态单分配形式这样的优化,它允许将num后续读取视为使用常量5 ,因此由于其实际值,它们可以将其视为int ,但是通常,效果是用可预测的结果代替计算,从而根本不需要存储值。


¹堆的大小不必与理论上可寻址的内存一样大,因此具有CompressedOOP的 JVM仅在32位架构上使用32位作为对象引用,只要堆小于对齐 ×2³²,即默认值为32GiB对准。

暂无
暂无

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

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