Java—空变量是否需要内存空间

Java—空变量是否需要内存空间,java,Java,考虑以下代码块: class CheckStore { private String displayText; private boolean state; private String meaningfulText; private URL url; public CheckStore(String text, boolean state) { this.displayText = text; this.state =

考虑以下代码块:

class CheckStore {
    private String displayText;
    private boolean state;
    private String meaningfulText;
    private URL url;

    public CheckStore(String text, boolean state) {
        this.displayText = text;
        this.state = state;
    }
    :
    :
}
在构造函数中初始化两个变量(
displayText
state
)时,其他两个变量(
meaningfulText
url
)是否需要内存中的空间来存储
null

问题1。如果它们确实需要空间,那么
null
值在内存中占用多少内存? (例如,
int
需要4个字节)


问题2。字符串在内存中占用多少空间?一个字符串需要多少内存空间?它是否取决于字符串的长度

在Java中,
null
只是一个引用(基本上是一个受限指针)可以拥有的值。这意味着引用没有任何内容。在这种情况下,仍然会使用引用的空间。在32位系统上为4字节,在64位系统上为8字节。但是,在实际分配引用指向的类的实例之前,不会为引用指向的类占用任何空间

编辑:就字符串而言,Java中的
字符串
每个字符需要16位(2字节),加上少量的簿记开销,这可能是未记录的和特定于实现的。

我想补充:

  • 引用类型的变量将初始化为空值
  • null不是对象。因为(对象的null instanceof)等于false
  • JVM中只有一个空值。不管有多少变量引用null

    对象s=(字符串)null

    对象i=(整数)null

    System.out.println(s==i)//真的

  • 您可以使用获取该类的布局。(但是要小心,您可能需要对其背后的机制有更深入的了解,不要盲目相信结果,并且要知道这只是对当前使用的虚拟机的一个估计(在我的例子中为1.7.0_76 x64 win:):

    我使用CLI版本我想正确的方法是在项目中包含库,但无论如何,它似乎是这样工作的:

    test>java -cp target\classes;jol-cli-0.3.1-full.jar org.openjdk.jol.Main internals test.CheckStore
    Running 64-bit HotSpot VM.
    Using compressed oop with 0-bit shift.
    Using compressed klass with 0-bit shift.
    Objects are 8 bytes aligned.
    Field sizes by type: 4, 1, 1, 2, 2, 4, 4, 8, 8 [bytes]
    Array element sizes: 4, 1, 1, 2, 2, 4, 4, 8, 8 [bytes]
    
    VM fails to invoke the default constructor, falling back to class-only introspection.
    
    test.CheckStore object internals:
     OFFSET  SIZE    TYPE DESCRIPTION                    VALUE
          0    12         (object header)                N/A
         12     1 boolean CheckStore.state               N/A
         13     3         (alignment/padding gap)        N/A
         16     4  String CheckStore.displayText         N/A
         20     4  String CheckStore.meaningfulText      N/A
         24     4     URL CheckStore.url                 N/A
         28     4         (loss due to the next object alignment)
    Instance size: 32 bytes (estimated, the sample instance is not available)
    Space losses: 3 bytes internal + 4 bytes external = 7 bytes total
    
    自动压缩oops关闭时也是如此:

    test>java -XX:-UseCompressedOops -cp target\classes;jol-cli-0.3.1-full.jar org.openjdk.jol.Main internals test.CheckStore
    Running 64-bit HotSpot VM.
    Objects are 8 bytes aligned.
    Field sizes by type: 8, 1, 1, 2, 2, 4, 4, 8, 8 [bytes]
    Array element sizes: 8, 1, 1, 2, 2, 4, 4, 8, 8 [bytes]
    
    VM fails to invoke the default constructor, falling back to class-only  introspection.
    
    test.CheckStore object internals:
     OFFSET  SIZE    TYPE DESCRIPTION                    VALUE
          0    16         (object header)                N/A
         16     1 boolean CheckStore.state               N/A
         17     7         (alignment/padding gap)        N/A
         24     8  String CheckStore.displayText         N/A
         32     8  String CheckStore.meaningfulText      N/A
         40     8     URL CheckStore.url                 N/A
    Instance size: 48 bytes (estimated, the sample instance is not available)
    Space losses: 7 bytes internal + 0 bytes external = 7 bytes total
    
    这些只是对象本身的布局如果字段为空,那么它将不会指向更多的对象,否则您还必须查看目标类型(
    URL
    String
    )。不能在内存中跳过空字段,因为它需要在分配实例时调整实例的大小。因此,这些字段都是预构造的,它们只是不引用堆上其他位置的已分配对象


    注意:如果实现默认构造函数,您将获得更多详细信息,但在这种特定情况下,大小将是相同的。如果您想知道字段的顺序和填充来自何处,您可以检查-(基本上,它按8字节对齐对象,按大小排序字段,将同一类型分组在一起,最后引用。超类型中的字段首先对齐,4字节对齐。)

    Null表示0。通常在内存中定义一个空位置。每当使用编程语言指向它时,所有内容都指向同一个位置。这意味着空位置只消耗一个4字节内存。那么指向它的任何内容都不会消耗更多内存。空位置的定义是特定于语言的,但定义为void*ptr=0;是无效的java和C++中常见的。Java必须对它进行类似的定义。不可能指向OC。你必须指向某个东西。但是我们定义了一个公共的“没有”,并且所有的东西指向它只消耗那个空间。

    @ YaTeNDRA:指针必须足够大,以跨越整个地址空间。因此,在32位的机器上,你需要32位。在64位计算机上,您需要64位。不一定……HotSpot中有一些有趣的工作可以避免这种情况:@Jon Skeet:非常有趣,我没有意识到这一点。我将对它们进行重新表述:在没有非常聪明且无法保证的JIT优化的情况下,如果您有64位地址空间,则需要64位引用。@Knownasilya:I移动到@JonSkeet共享的原始链接的t已失效。后来者可能引用和1。引用类型的成员变量初始化为null。局部变量不是。2.null不是
    对象
    ,不是因为
    null instanceof Object
    为false,而是因为null是引用。3.JVM中的null值与ha一样多我们是由(a)ast_null操作码(b)成员变量初始化(c)等创建的。该语句没有意义。
    null
    始终等于自身,但这并不意味着任何身份。引用始终是对象指针的大小(压缩或32位虚拟机上有4个字节,未压缩64位虚拟机上有8个字节)。null值和其他值之间没有区别(只是在null情况下没有引用另一个对象)