在Java语言中,堆和栈都是存储数据的地方。变量分为基本数据类型和引用类型,基本数据类型的变量(int,short,long,byte,float,double,boolean,char)以及对象的引用变量,其内存都分配在栈上,变量出了作用域就会自动释放,而引用类型的变量,器内存分配在堆上或者常量池(字符串常量和基本数据类型常量)中,通过new等方式创建;
具体而言,栈内存主要用来存放基本数据类型与引用变量。栈内存的管理是通过压栈和弹栈操作来完成,以栈帧为基本单位来管理程序的调用关系,每当有新的函数调用时,都会通过压栈的方式创建新的栈帧,每当函数调用结束后都会通过弹栈的方式来释放栈帧;
对内存用于存放运行时创建 的对象。一般来讲,通过new关键字创建出来的对象都存储在堆内存中。由于JVM是基于堆栈的虚拟机,而每个java程序都运行在一个单独的JVM实例上,每一个实例唯一对应一个堆,一个java程序内的多线程也就运行在同一个JVM实例上,因此这些线程之间会共享堆内存。鉴于此多线程在访问堆中的数据时需要对数据进行同步。
在C++中,堆内存的管理都是由开发人员来负责的,也就是说开发人员在堆中申请内存,当不再使用时,必须有开发人员来完成堆内存释放的工作。而java语言中这个内存释放的工作由垃圾回收器来负责完成。
在堆中产生了一个,数组或对象后,还可以在栈中定义一个特殊的变量,让栈中变量的取值等于数组或对象在堆内存中的首地址,栈中的这个变量就成了数组或对象的引用变量。引用变量就等于是为数组或对象起了一个名称。以后就可以在程序中使用栈中的引用变量来访问堆中的数组或对象。这就是Java中引用的用法。
从堆和栈的功能级作用来比较,堆主要用来存放对象,栈主要用来执行程序的。相比较与堆,站的存取速度更快,胆颤的大小和生存期必须是确定的,因此缺乏一定的灵活性。而堆却可以在运行是动态分配内存,生存期不用提前告诉编译器,但这也导致了其存其速度的缓慢。
public class Test {
public static void main(String[] args) {
int i = 10;
Rectangle r = new Rectangle(4, 6);
}
}
class Rectangle {
private int width;
private int height;
public Rectangle(int width, int height) {
this.width = width;
this.height = height;
}
}
由于i为基本数据类型的局部变量,因此它存储在栈空间中,而r为对象的引用,因此也被存储在栈空间中;实际的对象存储在堆空间中,当main方法退出后,存储在栈中的i和r通过压栈和弹栈的操作将会在栈中被回收,而存储在堆中的对象将会有垃圾回收器来自动回收。