程序运行时三种内存分配策略:静态的、栈式的、和堆式的,以及区别
按照编译原理的观点,程序运行时的内存分配有三种策略,分别是静态的,栈式的,和堆式的
静态存储分配是指在编译时就能确定每个数据目标在运行时刻的存储空间需求,因而在编译时就可以给他们分配固定的内存空间.
这种分配策略要求程序代码中不允许有可变数据结构(比如可变数组)的存在,也不允许有嵌套或者递归的结构出现,因为它们都会导致编译程序无法计算准确的存储空间需求.
栈式存储分配也可称为动态存储分配,是由一个类似于堆栈的运行栈来实现的.
和静态存储分配相反,在栈式存储方案中,程序对数据区的需求在编译时是完全未知的,
只有到运行的时候才能够知道,
但是规定在运行中进入一个程序模块时,必须知道该程序模块所需的数据区大小才能够为其分配内存.
和我们在数据结构所熟知的栈一样,栈式存储分配按照先进后出的原则进行分配。
java内存分配中的内存栈 和数据结构中的 栈 是一个性质的,先进后出
静态存储分配要求在编译时能知道所有变量的存储要求,栈式存储分配要求在过程的入口处必须知道所有的存储要求,
堆式存储分配则专门负责在编译时或运行时模块入口处都无法确定存储要求的数据结构的内存分配,比如可变长度串和对象实例.
堆由大片的可利用块或空闲块组成,堆中的内存可以按照任意顺序分配和释放.
堆是应用程序在运行的时候请求操作系统分配给自己内存,由于从操作系统管理的内存分配,所以在分配和销毁时都要占用时间,因此用堆的效率非常低.
但是堆的优点在于,编译器不必知道要从堆里分配多少存储空间,也不必知道存储的数据要在堆里停留多长的时间,因此,用堆保存数据时会得到更大的灵活性
每一个Java应用都唯一对应一个JVM实例,每一个实例唯一对应一个堆。
应用程序在运行中所创建的所有类实例或数组都放在这个堆中,并由应用所有的线程共享.跟C/C++不同,Java中分配堆内存是自动初始化的。
Java中所有对象的存储空间都是在堆中分配的,但是这个对象的引用却是在堆栈中分配,也就是说在建立一个对象时从两个地方都分配内存,
在堆中分配的内存实际建立这个对象,而在堆栈中分配的内存只是一个指向这个堆对象的指针(引用)而已。