Java对象的内存分配过程中的步骤
当类实例化以下对象时,内存中会发生什么?
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");
如何将内存分配给新实例化的对象及其属性?
让我们一步一步:
SomeObject so1 = new SomeObject("some property value");
…实际上比看起来更复杂,因为你正在创建一个新的String。 可能更容易想到:
String tmp = new String("some property value"); SomeObject so1 = new SomeObject(tmp); // Not that you would normally write it in this way.
(绝对准确 – 这些并不是真正等效。在原始的’new String’是在编译时创建的,并且是.class映像的一部分。你可以把它想象成一个性能破解。)
因此,首先JVM为String分配空间。 您通常不知道或不关心String实现的内部,所以只需要相信一块内存被用来表示“某些属性值”。 此外,您有一些临时分配的内存,其中包含对String的引用。 在第二种forms中,它明确地称为tmp
; 在您的原始formsJava处理它而不命名它。
接下来,JVM为新的SomeObject分配空间。 这为Java的内部簿记提供了一些空间,并为每个对象的字段提供了空间。 在这种情况下,只有一个字段strSomeProperty
。
请记住, strSomeProperty
只是对String的引用。 现在,它将被初始化为null。
接下来,执行构造函数。
this.strSomeProperty = strSomeProperty;
所有这一切都是将对String的引用复制到strSomeProperty
字段中。
最后,为对象引用so1
分配空间。 这是通过引用SomeObject来设置的。
so2
以完全相同的方式工作。
由Heinz M. Kabutz博士确定Java中的内存使用情况给出了一个精确的答案,以及一个计算内存使用情况的程序。 相关部分:
- 该类占用至少8个字节。 所以,如果你说新的Object(); 你将在堆上分配8个字节。
- 每个数据成员占用4个字节,long和double除外,占用8个字节。 即使数据成员是一个字节,它仍然会占用4个字节! 此外,使用的内存量以8字节块增加。 因此,如果你有一个包含一个字节的类,它将占用该类8个字节,数据占8个字节,总共16个字节(呻吟!)。
- 数组有点聪明。 基元被打包成数组,所以如果你有一个字节数组,它们每个都会占用一个字节(哇!)。 当然,内存使用量仍以8字节为单位。
正如人们在评论中指出的那样,字符串是一个特例,因为它们可以被实习。 您可以以相同的方式推断它们占用的空间,但请记住,看起来像同一个String的多个副本的内容实际上可能指向相同的引用。
要记住的要点:
- 调用方法时,会在堆栈顶部创建一个框架。
- 一旦方法完成执行,控制流将返回到调用方法,并刷新其相应的堆栈帧。
- 在堆栈中创建局部变量。
- 实例变量在堆中创建,并且是它们所属对象的一部分。
- 在堆栈中创建引用变量。
参考: http : //www.javatutorialhub.com/java-stack-heap.html