Java 把内存划分成两种:一种是栈内存,另一种是堆内存。在函数中定义的一
些基本类型的变量和对象的引用变量都是在函数的栈内存中分配,当在一段代
码块定义一个变量时,Java 就在栈中为这个变量分配内存空间,当超过变量的
作用域后,Java 会自动释放掉为该变量分配的内存空间,该内存空间可以立即
被另作它用。
堆内存用来存放由 new 创建的对象和数组,在堆中分配的内存,由 Java
虚拟机的自动垃圾回收器来管理。在堆中产生了一个数组或者对象之后,还可
以在栈中定义一个特殊的变量,让栈中的这个变量的取值等于数组或对象在堆
内存中的首地址,栈中的这个变量就成了数组或对象的引用变量,以后就可以
在程序中使用栈中的引用变量来访问堆中的数组或者对象,引用变量就相当于
是为数组或者对象起的一个名称。引用变量是普通的变量,定义时在栈中分配,
引用变量在程序运行到其作用域之外后被释放。而数组和对象本身在堆中分配,
即使程序运行到使用 new 产生数组或者对象的语句所在的代码块之外,数组
和对象本身占据的内存不会被释放,数组和对象在没有引用变量指向它的时候,
才变为垃圾,不能在被使用,但仍然占据内存空间不放,在随后的一个不确定
的时间被垃圾回收器收走(释放掉)。
这也是 Java 比较占内存的原因,实际上,栈中的变量指向堆内存中的变量,
这就是 Java 中的指针!
java 中内存分配策略及堆和栈的比较
2.1 内存分配策略
按照编译原理的观点,程序运行时的内存分配有三种策略,分别是静态的,栈
式的,和堆式的.
静态存储分配是指在编译时就能确定每个数据目标在运行时刻的存储空间
需求,因而在编译时就可以给他们分配固定的内存空间.这种分配策略要求程序
代码中不允许有可变数据结构(比如可变数组)的存在,也不允许有嵌套或者递归
的结构出现,因为它们都会导致编译程序无法计算准确的存储空间需求.
栈式存储分配也可称为动态存储分配,是由一个类似于堆栈的运行栈来实现
的.和静态存储分配相反,在栈式存储方案中,程序对数据区的需求在编译时是完
全未知的,只有到运行的时候才能够知道,但是规定在运行中进入一个程序模块
时,必须知道该程序模块所需的数据区大小才能够为其分配内存.和我们在数据
结构所熟知的栈一样,栈式存储分配按照先进后出的原则进行分配。
静态存储分配要求在编译时能知道所有变量的存储要求,栈式存储分配要求
在过程的入口处必须知道所有的存储要求,而堆式存储分配则专门负责在编译时
或运行时模块入口处都无法确定存储要求的数据结构的内存分配,比如可变长度
串和对象实例.堆由大片的可利用块或空闲块组成,堆中的内存可以按照任意顺
序分配和释放.