简体   繁体   English

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

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

If we run this line of code 如果我们运行这一行代码

long num = 5;

Does this variable have 64 bits of space? 这个变量有64位空间吗? Or is the size determined by the value put in side? 还是大小取决于旁边的值? Logically it should be 64 bits as primitive datatypes are mutable. 从逻辑上讲,它应为64位,因为原始数据类型是可变的。 But is my conclusion true? 但是我的结论是真的吗?

Furthermore, if we have an immutable object such as a string 此外,如果我们有一个不变的对象,例如字符串

String str = "Hello World";

Giving this String the maximum memory by default seems counter intuitive. 默认情况下,将此字符串赋予最大内存似乎很不直观。 If you were to set a String and then change it you would just change the pointer into the memory address of the second String, the newly created one. 如果要设置一个String然后进行更改,则只需将指针更改为第二个String(新创建的String)的内存地址即可。

Could someone please answer this question or point me in the right direction? 有人可以回答这个问题或为我指出正确的方向吗?

long is a 64-bit primitive value, regardless of what actual value you keep inside. long是一个64-bit原始值,无论您保留的是什么实际值。

String is a class that wraps a char[] . String是包装char[] The internal array has different sizes depending on the amount of characters inside. 内部数组的大小取决于内部字符的数量。 16-bits ¹ per char . 每个char 16-bits ¹。

¹ It's a bit more complicated than that, but generally speaking it's 16-bits per char. ¹比这复杂一点,但通常来说,每个字符16位。

From JLS §4.2 and §4.2.1 : 根据JLS§4.2§4.2.1

The integral types are byte, short, int, and long, whose values are 8-bit, 16-bit, 32-bit and 64-bit signed two's-complement integers, respectively, and char, whose values are 16-bit unsigned integers representing UTF-16 code units (§3.1). 整数类型为byte,short,int和long,其值分别为8位,16位,32位和64位有符号的二进制补码整数,以及char,其值为16位无符号整数。代表UTF-16代码单元(第3.1节)。

The floating-point types are float, whose values include the 32-bit IEEE 754 floating-point numbers, and double, whose values include the 64-bit IEEE 754 floating-point numbers. 浮点类型为浮点型,其值包括32位IEEE 754浮点数;以及双精度型,其值包括64位IEEE 754浮点数。

Clearly for these primitives to be able to have minimum and maximum values, they need to be represented by a fixed amount of memory, so it cannot be variable. 显然,为了使这些原语能够具有最小值和最大值,它们需要用固定数量的内存表示,因此它不能可变。

Regarding String , each object is backed by a char[] (up until JDK 9), which has a fixed length. 关于String ,每个对象都有一个char[] (直到JDK 9)支持,该char[]具有固定的长度。

There are different kind of variables, hence, there is not a single answer. 有不同种类的变量,因此,没有一个答案。

Heap variables, also known as fields , usually have a size matching the data type, sometimes even more, depending on alignment considerations, but always enough to be able to hold any valid value of the data type. 堆变量(也称为字段 )通常具有与数据类型匹配的大小,有时甚至更多,具体取决于对齐方式,但始终足以容纳数据类型的任何有效值。 As you already mentioned yourself, a reference type points to an object in the heap memory and assigning it another reference just changes the address, so a variable of a reference type has a fixed size being able to store a heap memory address¹, regardless of the size of the referenced object. 就像您自己已经提到的那样, 引用类型指向堆内存中的一个对象,然后为另一个对象分配引用只会更改地址,因此引用类型的变量具有固定大小,能够存储堆内存地址¹,无论引用对象的大小。 Since String instances are immutable, reassigning is the only way to change a String variable. 由于String实例是不可变的,因此重新分配是更改String变量的唯一方法。

For local variables, the picture is different. 对于局部变量,情况有所不同。 Here, processing speed is more important than reducing memory consumption. 在这里,处理速度比减少内存消耗更为重要。 So the data types, boolean , byte , short , char , and int are all uniformly treated as int , which you already notice on source code level, as all arithmetic done on these data types (except boolean ) results in an int . 因此,数据类型booleanbyteshortcharint都统一视为int ,您已经在源代码级别上注意到了,因为在这些数据类型上进行的所有算术运算( boolean除外)都得出int This transformation already happens at compile-time. 这种转换已经在编译时发生。 A JVM could re-establish smaller storage types when optimizing the code at runtime, but that's not the usual direction. 在运行时优化代码时,JVM可以重新建立较小的存储类型,但这不是通常的方向。 Local variables are more likely to be mapped to CPU registers, not having any storage at all. 局部变量更有可能映射到CPU寄存器,而根本没有任何存储空间。 Or, if you count registers as storage, they are at least 32 bit wide, rather 64 bit on most of today's systems. 或者,如果将寄存器计为存储,则它们的宽度至少为32位,而在当今大多数系统中为64位。

To stay with your long num = 5; 保持你的long num = 5; example, JVMs like HotSpot use optimizations like Static single assignment form , which allows to treat subsequent reads of num as if they were using the constant 5 , so they could treat it like an int due to its actual value, but usually, the effect is to replace calculations by their predictable result which eliminates the need to store the value at all. 例如,像HotSpot这样的JVM使用诸如静态单分配形式这样的优化,它允许将num后续读取视为使用常量5 ,因此由于其实际值,它们可以将其视为int ,但是通常,效果是用可预测的结果代替计算,从而根本不需要存储值。


¹ the heap doesn't have to be as large as the theoretically addressable memory, so JVMs with CompressedOOPs use only 32 bits for object references on 64 bit architectures, as long as the heap is smaller than alignment ×2³², ie 32GiB with the default alignment. ¹堆的大小不必与理论上可寻址的内存一样大,因此具有CompressedOOP的 JVM仅在32位架构上使用32位作为对象引用,只要堆小于对齐 ×2³²,即默认值为32GiB对准。

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

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