在java中,堆和栈有着极其重要的地位。我们知道堆(heap)和 栈(stack)都是为Java提供数据管理的一块内存空间,
位于RAM中,速度仅次于cpu中的寄存器。但是堆和栈有什么区别呢?
栈:栈中存取的数据事先应说明周期性和内存大小,故灵活性较差,但反观它的存
取速度快,且在栈中的数据可以共享。
堆:堆空间中存取的数据不必事先说明所占空间大小和周期性,所以堆具有灵活性
但由于数据的空间大小以及周期性是在程序运行期间动态分配时得知的,故存取
速度相对慢于栈。
堆和栈又分别存储哪些数据呢?
- 堆: 堆中存储的时程序运行时动态分配的实体对象和数组,不存储对象的引用(指针)。
- 栈:栈中存储着基本数据类型和String类型以及类的实例对象的引用对象。
- 方法区:堆中还存在着一个方法区(静态区),方法区存储的是一些永远不变或唯一的内容,如静态变量,类信息(class对象),字符串常量。
栈帧:
线程创建的同时会创建一个私有栈,在栈中当jvm调用一个方法时会在栈中新开辟一个栈帧,栈帧的大小在jvm调用方法时会在class文件中获取(通过方法的局部变量,算法等计算出所需的word size)。一个栈帧中包含着方法的局部变量和操作数栈还有栈数据。
栈属于线程私有的,栈与栈之间不共享数据,jvm中只有一块堆空间,是线程共享的。
以下是一张草图(很草率画的图,故称草图)
接着贴出代码示例加强理解:
public class HeapAndStackTest { //方法区中存储着class信息
int heapOne;
double heapTwo; //heapOne和heapTwo属于成员变量,存储在对象的实体中,即在堆中
static int a; //静态变量和静态方法 存储在堆中的方法区(静态区)中
public int fun(int a ,int b) {
int c = 1;
int d = 2; //参数列表和局部变量 还有 算法(operand stack)都在栈帧中
if((a>c)&&(b>d)) {//栈帧的大小取决于局部变量的大小和算法复杂性
System.out.println("operand stack//操作栈");
}
return 0;
}
public static void main(String[] args) { //jvm自动调用main方法(主线程)
HeapAndStackTest object = new HeapAndStackTest();
//object对象引用(指针)在栈中,对象实体在堆中
object.fun(2, 1);//在栈中为每个方法开辟一个栈帧
//调用了fun方法,在栈的栈帧中将fun方法push到栈顶,对数据及状态进行保存
}
}
这些便是本小白对堆栈的一些理解,难免有些错误之处,请批评指教。