Java 对象的内存分配过程中的步骤

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/320980/
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-11 13:08:30  来源:igfitidea点击:

Steps in the memory allocation process for Java objects

javamemoryobjectheap

提问by DragonBorn

What happens in the memory when a class instantiates the following object?

当一个类实例化以下对象时,内存中会发生什么?

public class SomeObject{

    private String strSomeProperty;

    public SomeObject(String strSomeProperty){
        this.strSomeProperty = strSomeProperty;
    }
    public void setSomeProperty(String strSomeProperty){
        this.strSomeProperty = strSomeProperty;
    }
    public String getSomeProperty(){
        return this.strSomeProperty;
    }
}

In class SomeClass1:

在课堂上SomeClass1

SomeObject so1 = new SomeObject("some property value");

In class SomeClass2:

在课堂上SomeClass2

SomeObject so2 = new SomeObject("another property value");

How is memory allocated to the newly instantiated object and its properties?

内存是如何分配给新实例化的对象及其属性的?

采纳答案by slim

Let's step through it:

让我们一步一步来:

SomeObject so1 = new SomeObject("some property value");

... is actually more complicated than it looks, because you're creating a new String. It might be easier to think of as:

...实际上比看起来更复杂,因为您正在创建一个新字符串。可能更容易想到:

String tmp = new String("some property value");
SomeObject so1 = new SomeObject(tmp);
// Not that you would normally write it in this way.

(To be absolutely accurate - these are not really equivalent. In the original the 'new String' is created at compile time and is part of the .class image. You can think of this as a performance hack.)

(绝对准确 - 这些并不是真正等效的。在原始版本中,“新字符串”是在编译时创建的,并且是 .class 映像的一部分。您可以将其视为性能黑客。)

So, first the JVM allocates space for the String. You typically don't know or care about the internals of the String implementation, so just take it on trust that a chunk of memory is being used to represent "some property value". Also, you have some memory temporarily allocated containing a reference to the String. In the second form, it's explicitly called tmp; in your original form Java handles it without naming it.

因此,首先 JVM 为 String 分配空间。您通常不知道或不关心 String 实现的内部结构,因此只需相信一块内存用于表示“某些属性值”。此外,您临时分配了一些内存,其中包含对字符串的引用。在第二种形式中,它被明确称为tmp; 在您的原始形式中,Java 会在不命名的情况下处理它。

Next the JVM allocates space for a new SomeObject. That's a bit of space for Java's internal bookkeeping, and space for each of the object's fields. In this case, there's just one field, strSomeProperty.

接下来,JVM 为新的 SomeObject 分配空间。这是 Java 内部簿记的一点空间,也是对象的每个字段的空间。在这种情况下,只有一个字段strSomeProperty.

Bear in mind that strSomePropertyis just a reference to a String. For now, it'll be initialised to null.

请记住,这strSomeProperty只是对字符串的引用。现在,它将被初始化为 null。

Next, the constructor is executed.

接下来,构造函数被执行。

this.strSomeProperty = strSomeProperty;

All this does is copy the referenceto the String, into your strSomePropertyfield.

所有这些都是将对该字符串的引用复制到您的strSomeProperty字段中。

Finally, space is allocated for the object reference so1. This is set with a reference to the SomeObject.

最后,为对象引用分配空间so1。这是通过引用 SomeObject 来设置的。

so2works in exactly the same way.

so2以完全相同的方式工作。

回答by Craig P. Motlin

Determining Memory Usage in Javaby Dr. Heinz M. Kabutz gives a precise answer, plus a program to calculate the memory usage. The relevant part:

Heinz M. Kabutz 博士的Determining Memory Usage in Java给出了一个准确的答案,以及一个计算内存使用情况的程序。相关部分:

  1. The class takes up at least 8 bytes. So, if you say new Object(); you will allocate 8 bytes on the heap.
  2. Each data member takes up 4 bytes, except for long and double which take up 8 bytes. Even if the data member is a byte, it will still take up 4 bytes! In addition, the amount of memory used is increased in 8 byte blocks. So, if you have a class that contains one byte it will take up 8 bytes for the class and 8 bytes for the data, totalling 16 bytes (groan!).
  3. Arrays are a bit more clever. Primitives get packed in arrays, so if you have an array of bytes they will each take up one byte (wow!). The memory usage of course still goes up in 8 byte blocks.
  1. 该类至少占用 8 个字节。所以,如果你说 new Object(); 您将在堆上分配 8 个字节。
  2. 每个数据成员占用 4 个字节,除了 long 和 double 占用 8 个字节。即使数据成员是一个字节,它仍然会占用4个字节!此外,使用的内存量以 8 字节块为单位增加。因此,如果您有一个包含 1 个字节的类,它将占用该类的 8 个字节和数据的 8 个字节,总共 16 个字节(呻吟!)。
  3. 数组更聪明一点。原语被打包成数组,所以如果你有一个字节数组,它们每个都会占用一个字节(哇!)。当然,内存使用量仍然以 8 字节块为单位增加。

As people have pointed out in the comments, Strings are a special case, because they can be interned. You can reason about the space they take up in the same way, but keep in mind that what looks like multiple copies of the same String may actually point to the same reference.

正如人们在评论中指出的那样,字符串是一个特例,因为它们可以被实习。您可以以相同的方式推断它们占用的空间,但请记住,看起来像同一个 String 的多个副本实际上可能指向同一个引用。

回答by Shishir

Points to remember:

要记住的要点:

  1. When a method is called, a frame is created on the top of stack.
  2. Once a method has completed execution, flow of control returns to the calling method and its corresponding stack frame is flushed.
  3. Local variables are created in the stack.
  4. Instance variables are created in the heap & are part of the object they belong to.
  5. Reference variables are created in the stack.
  1. 调用方法时,会在堆栈顶部创建一个框架。
  2. 一旦方法完成执行,控制流将返回到调用方法并刷新其相应的堆栈帧。
  3. 局部变量在堆栈中创建。
  4. 实例变量在堆中创建并且是它们所属对象的一部分。
  5. 引用变量在堆栈中创建。

Ref: http://www.javatutorialhub.com/java-stack-heap.html

参考:http: //www.javatutorialhub.com/java-stack-heap.html