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

时间:2017-12-05 13:48:26

标签: java memory memory-management

如果我们运行这行代码

long num = 5;

这个变量有64位空间吗?或者尺寸是由放在一边的值决定的?逻辑上它应该是64位,因为原始数据类型是可变的。但我的结论是真的吗?

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

String str = "Hello World";

默认情况下,为此String提供最大内存似乎是反直觉的。如果您要设置一个字符串然后更改它,您只需将指针更改为第二个字符串的内存地址,即新创建的字符串。

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

3 个答案:

答案 0 :(得分:2)

long是一个64-bit原始值,无论您保留在哪个实际值内。

String是一个包装char[]的类。内部数组具有不同的大小,具体取决于内部的字符数。 16-bits¹char

¹它比这复杂一点,但一般来说每个字符都是16位。

答案 1 :(得分:1)

来自JLS §4.2§4.2.1

  

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

     

浮点类型是float,其值包括32位IEEE 754浮点数和double,其值包括64位IEEE 754浮点数。

显然,这些基元能够具有最小值和最大值,它们需要由固定数量的内存表示,因此它不能变化。

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

答案 2 :(得分:1)

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

堆变量,也称为字段,通常具有与数据类型匹配的大小,有时甚至更多,具体取决于对齐注意事项,但始终足以保存数据的任何有效值类型。正如您已经提到的那样,引用类型指向堆内存中的对象并为其分配另一个引用只是更改地址,因此引用类型的变量具有可以存储的固定大小堆内存地址¹,与引用对象的大小无关。由于String实例是不可变的,因此重新分配是更改String变量的唯一方法。

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

要继续使用long num = 5;示例,像HotSpot这样的JVM使用Static single assignment form之类的优化,这样可以处理num的后续读取,就像它们使用常量5一样因此,由于其实际价值,他们可以像int那样对待它,但通常,效果是用可预测的结果取代计算,这样就不需要存储值了。

¹堆不必像理论上可寻址的内存一样大,因此只要堆较小,具有 CompressedOOPs 的JVM在64位体系结构上仅使用32位进行对象引用比 alignment ×2³²,即32GiB与默认对齐。