Java 堆栈和堆
什么是堆栈内存?
Java 中的堆栈是内存的一部分,包含方法、局部变量和引用变量。堆栈存储器始终以**后进先出(LIFO)**顺序引用。局部变量是在堆栈中创建的。
什么是堆内存?
堆是包含对象的内存部分,也可能包含引用变量。实例变量在堆中创建的。
Java 中的内存分配
JVM 将内存划分为以下部分。
- 堆
- 堆栈
- 代码
- 静态
这种内存划分是其有效管理所必需的。
- 代码部分包含字节码。
- 内存的堆栈部分包含方法、局部变量和引用变量。
- 堆部分包含对象(也可能包含引用变量)。
- 静态部分包含静态数据/方法。
本地和实例变量之间的差异
实例变量在类中声明而不是在方法内声明的。
class Student{
int num; //num is instance variable
public void showData{}
局部变量在方法中声明,包括方法参数。
public void sum(int a){
int x = int a + 3;
//a , x are local variables;
}
堆栈和堆之间的区别
让我们举个例子来更好地理解这一点。
想一下你的 main
方法调用方法 m1
,
public void m1{
int x=20
}
在 Java 堆栈中,将从方法 m1
创建一个帧。m1
中的变量 X 也将在堆栈 m1
的帧中创建。
方法 m1
调用方法 m2
。在堆栈中,在 m1
帧的顶部为 m2
创建一个新帧。
变量 b
和 c
也将在堆栈中的帧 m2
中创建。
public void m2(int b){
boolean c;
}
同样的,方法 m2
来调用方法 m3
。再次在堆栈顶部创建一个帧 m3
。
现在假设我们的方法 m3
正在为类 Account
创建一个对象,它有两个实例变量 int p
和 int q
。
Account {
Int p;
Int q;
}
这是方法 m3
的代码
public void m3(){
Account ref = new Account();
//more code
}
语句 new Account()
将在堆中创建一个 Account
对象。
引用变量 ref
将在堆栈中创建。赋值 =
运算符将使引用变量指向堆中的对象。
一旦方法完成执行。控制流程将返回调用方法。在这里指的是方法 m2
。
方法 m3
的堆栈将被清除。
由于引用变量将不再指向堆中的对象,因此它可以进行垃圾回收。
方法 m2
完成执行后。它将从堆栈弹出,其所有变量将被刷新,不再可用。同样这适用于方法 m1
。
最终,控制流程将返回程序的起始点。通常,这是 main
方法。
如果 Object 有一个引用作为其实例变量怎么办?比如下面,
public static void main(String args[]) {
A parent = new A();
//more code }
class A{
B child = new B();
int e; //more code
}
class B{
int c;
int d;
//more code
}
}
在这种情况下,引用变量 child
将在堆中创建,而堆又将指向其对象,如下图所示。
![Java Stack and Heap](/img/JavaJava Stack and Heap.jpg)
概要:
- 调用方法时,会在堆栈顶部创建一个帧。
- 一旦方法完成执行,控制流将返回到调用方法,并刷新其相应的堆栈帧。
- 在堆栈中创建局部变量。
- 实例变量在堆中创建并且是它们所属对象的一部分。
- 在堆栈中创建引用变量。