Java内存管理之堆和栈
我们都知道Java程序是运行在JVM(Java Virtual Machine)上的,我们可以把JVM理解成Java程序和操作系统之间的桥梁,而Java内存分配也都是基于JVM中进行的。 Java程序运行过程会涉及到两大重要的内存区域——堆和栈。
栈
- JVM会为每一个方法的调用在栈中分配一个对应的空间,这个空间称为该方法的栈帧,用于存储局部变量表、操作数、动态链接、方法出口信息等。
- 当某一个方法调用完成后,其对应的栈帧将被清除。
- 当栈内存储的内容是:
- 由基本数据类型声明的局部变量时,在栈中存储的是它们对应的具体数值。
- 局部对象的引用(定义在方法体中的引用类型变量),存储的是具体对象在堆中的地址。若对象的引用没有指向具体的空间,则是null。
堆
- 程序运行过程中动态产生的数据,比如new出来的对象,存放在堆中。
- 当对象使用结束,并确定已无实例引用指向堆空间时,JVM才会依据相关垃圾回收机制进行资源回收,完成堆内资源释放。也就是说,并不是方法结束,方法内涉及到的堆空间就会立即释放,这也是与栈管理不同的地方。
- 需要注意的是,创建出来的对象只包含属于各自的成员变量,并不包括成员方法。即同一个类的不同实例拥有各自的成员变量,存储在堆中的不同位置,但是同一个类的不同实例之间共享该类的方法,并不是每创建一个对象就把成员方法复制一次。
程序执行过程示例分析
public class Cat {
String name;
int month;
public void run(double weight) {
System.out.println("小猫已经" + weight + ",太重了,快去跑步");
}
}
public class CatTest {
public static void main(String[] args) {
Cat one = new Cat();
double wh = 200;
one.run(wh);
}
}
以上两个类位于同一个包下,程序执行流程如下:
- JVM自动寻找main方法,执行第一句代码,创建一个Cat类的实例one,在栈中分配一块内存,存放一个指向堆区对象的地址。譬如0x111111。
- 创建一个double型的变量wh,由于是基本数据类型,直接在栈中存放double对应的值200。
- 当调用one对象的run方法,并以wh为参数传入方法时,JVM检测到方法参数weight,作为方法局部变量,也会放入栈中,并将wh的值200复制给weight。
- 当完成run方法调用后,立即释放局部变量weight所占用的栈空间。
- main方法运行结束,立即释放栈中one,wh的空间,而堆中对象空间,则会当确定无引用指向该位置后,由垃圾回收机制进行回收,不会立即释放资源。
|