【问题标题】:Java - Does null variable require space in memoryJava - 空变量是否需要内存空间
【发布时间】:2011-01-26 16:52:28
【问题描述】:

考虑以下代码块:

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;
    }
    :
    :
}

当我在构造函数中初始化两个变量(displayTextstate)时,其他两个变量(meaningfulTexturl)是否需要内存空间来存储 null 值?

第一季度。如果它们确实需要空间,null 值在内存中占用多少内存? (例如int 占用 4 个字节)。

第二季度。一个字符串在内存中占用多少空间?一个字符串占用多少内存空间?它取决于字符串的长度吗?

【问题讨论】:

    标签: java


    【解决方案1】:

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

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

    【讨论】:

    【解决方案2】:

    我想补充:

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

      对象 s = (String)null;

      对象 i = (Integer)null;

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

    【讨论】:

    • 1. Member 引用类型的变量被初始化为空。局部变量不是。 2、null不是Object,不是因为null instanceof Object是假的,而是因为null是一个引用。 3. JVM 中的空值与由 (a) aconst_null 操作码 (b) 成员变量初始化 (c) 等创建的一样多。该语句没有意义。 null 总是等于它自己,但这并不意味着任何关于身份的事情。
    【解决方案3】:

    您可以使用jol 来获取该类的布局。 (但要小心,您可能需要对其背后的机制有更深入的了解,不要盲目相信结果,并注意这只是对当前使用的 VM 的估计(在我的情况下为 1.7.0_76 x64 获胜:):

    我使用 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
    

    如果您的字段为空,这些只是对象本身的布局,那么它将不会指向更多对象,否则您还必须查看目标类型(URLString)。 (如果您有所有实例的多个实例,则取决于您是多次使用相同的实例还是不同的实例)。不能在内存中跳过空字段,因为它需要在分配实例时调整其大小。所以这些字段都是预先构建的,它们只是不引用堆上其他地方的分配对象。

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

    【讨论】:

    • 引用始终是对象指针的大小(压缩或 32 位 VM 上为 4 字节,未压缩 64 位上为 8 字节)。 null 和其他值没有区别(只是在 NULL 的情况下没有引用另一个对象)
    【解决方案4】:

    Null 表示 0。通常在内存中定义一个位置 null。每当有人使用编程语言指向它时。一切都指向同一个地方。这意味着 NULL 只消耗一个 4 字节的内存。然后任何指向它的东西都不会消耗更多的内存。 NULL 的定义是特定于语言的,但定义它 void *ptr=0;在 C 和 C++ 中很常见。 JAVA 肯定也有类似的定义。不可能指向任何东西。你必须指出一些东西。但是我们定义了一个普通的无,所有指向它的东西都只消耗那个空间。

    【讨论】:

      猜你喜欢
      • 2015-11-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-08-17
      • 2011-07-24
      • 1970-01-01
      相关资源
      最近更新 更多