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


71

考虑以下代码块:

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值?

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

Q2。字符串在内存中占用多少空间?字符串需要占用多少存储空间?它取决于字符串的长度吗?

Answers:


64

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

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


2
@Yatendra:指针必须足够大以跨越整个地址空间。因此,在32位计算机上,您需要32位。在64位计算机上,您需要64位。
dsimcha 2010年

10
不一定...在HotSpot中有一些有趣的工作可以避免这种情况:wikis.sun.com/display/HotSpotInternals/CompressedOops
Jon Skeet 2010年

2
@Jon Skeet:非常有趣,我没有意识到。我将对它们进行重新表述:在没有非常聪明且不能保证的JIT优化的情况下,如果您具有64位地址空间,则需要64位引用。
dsimcha 2010年



14

我想补充:

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

    对象s =(String)null;

    对象i =(整数)null;

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


2
1.引用类型的成员变量初始化为null。局部变量不是。2. Null不是一个Object,不是因为它null instanceof Object为false,而是因为null是引用。3. JVM中的空值与(a)aconst_null操作码(b)成员变量初始化(c)等创建的值一样多。该语句没有任何意义。null总是等于自己,但这并不意味着身份。
user207421 '17

4

您可以使用jol来获取该类的布局。(但是要小心,您可能需要更深入地了解其背后的机制,不要盲目相信结果,并且要知道这只是当前使用的VM的估算值(在我的案例中为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

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

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


引用始终是对象指针的大小(压缩或32位VM上为4字节,未压缩64位上为8字节)。null和其他值之间没有区别(只是在NULL情况下还没有引用另一个对象)
eckes,2018年

1

Null表示0。在内存中通常定义一个空位。只要有人使用一种编程语言指向它。一切都指向同一个地方。这意味着NULL仅消耗一个4字节内存。然后,指向它的任何内容都不会消耗更多的内存。NULL的定义是特定于语言的,但将其定义为无效* ptr = 0; 在C和C ++中很常见。JAVA必须已经类似地定义了它。不可能一无所获。你必须指出一些东西。但是我们定义了一个共同的东西,所有指向它的东西都只占用那个空间。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.