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

2022-09-04 08:39:11

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

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

在课堂上 :SomeClass1

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

在课堂上 :SomeClass2

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

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


答案 1

让我们逐步了解一下:

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

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

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

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

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

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

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

接下来,执行构造函数。

this.strSomeProperty = strSomeProperty;

所有这一切都是为了将对字符串的引用复制到您的字段中。strSomeProperty

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

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


答案 2

Heinz M. Kabutz博士的《确定Java中的内存使用情况》给出了一个精确的答案,以及一个计算内存使用情况的程序。相关部分:

  1. 该类至少占用 8 个字节。所以,如果你说新的对象();您将在堆上分配 8 个字节。
  2. 每个数据成员占用 4 个字节,除了 long 和 double 占用 8 个字节。即使数据成员是一个字节,它仍然会占用4个字节!此外,使用的内存量在 8 个字节块中增加。因此,如果你有一个包含一个字节的类,它将占用8个字节作为类,8个字节用于数据,总共16个字节(呻吟!
  3. 数组更聪明一些。基元被打包在数组中,所以如果你有一个字节数组,它们将各自占用一个字节(哇!当然,内存使用量仍然在8字节块中上升。

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