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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2430655/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-13 07:31:40  来源:igfitidea点击:

Java - Does null variable require space in memory

java

提问by Yatendra Goel

Consider the following block of code:

考虑以下代码块:

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

When I initialize two variables (displayTextand state) in the constructor, do the other two variables (meaningfulTextand url) require space in the memory to store nullvalue?

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

Q1. If they do require space, how much memory does a nullvalue take in the memory? (ex. inttakes 4 bytes).

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

Q2. How much space does a string take in memory? How much memory space does a string take? Does it depend on the length of the string?

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

采纳答案by dsimcha

In Java, nullis just a value that a reference (which is basically a restricted pointer) can have. It means that the reference refers to nothing. In this case you still consume the space for the reference. This is 4 bytes on 32-bit systems or 8 bytes on 64-bit systems. However, you're not consuming any space for the class that the reference points to until you actually allocate an instance of that class to point the reference at.

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

Edit: As far as the String, a Stringin Java takes 16 bits (2 bytes) for each character, plus a small amount of book-keeping overhead, which is probably undocumented and implementation specific.

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

回答by Hymany

I'd like to add:

我想补充:

  1. variable of reference type will be initialized as null value.
  2. null is not object. because (null instanceof Object) equals to false
  3. there is only one null value in JVM. No matter how many variables refer to null.

    Object s = (String)null;

    Object i = (Integer)null;

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

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

    对象 s = (String)null;

    对象 i = (Integer)null;

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

回答by eckes

You can use jolto get the layout of that class. (However be careful, you might need a deeper understanding on the mechanics behind it, don't blindly trust the result and be aware it is just an estimate for the currently used VM (1.7.0_76 x64 win in my case:):

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

I use the CLI version I guess the proper method would be to include the library in your project, but anyway, it seems to work this way:

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

and the same with automatic compressed oops off:

与自动压缩 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

Those are only the layouts for the object itself if your fields are null, then it will not point to more objects, otherwise you have to look at the target types (URLand String) as well. (And if you have multiple instances of all of them it depends if you use the same multiple times or different ones). An null field cannot be skipped in memory, as it would require the instance to be resized when it is assigned. So the fields are all pre-constructed, they just do not reference allocated objects somewhere else on the heap.

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

NB: you get some more details if you implement a default constructor, but the sizing in this specific case would be the same. In case you wonder where the sequence and padding of fields is coming from, you can check this article- (basically it aligns objects on 8 bytes, sorts fields by size, groups same type together, references last. Fields from super types are first, 4 byte aligned.)

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

回答by Sidharth Singh

Null means 0. There is usually one place null defined in memory. Whenever one points to it using a programming language. Everything points to same place. It means only one 4 byte memory is consumed for NULL. Then whatever points to it does not consume any more memory. Definition of NULL is language specific but defining it void *ptr=0; is common in C and C++. JAVA must have defined it similarly. It is not possible to point to nothing ofc. You have to point to something. But we define a common nothing and everything points to it consume only that space.

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