heap、stack

Stack、Heap

202204121003501

引入

​ 堆和栈在平时开发中都在看不见的地方,但问题出的确是不少。在理解的时候总是有自相矛盾的点,借此梳理下相关的知识点。堆栈在不同领域有不同作用和解释,一下从编程和数据两个角度看看他们的特性。

编程

​ 在编程语言环境中,内存的分配主要为:堆分配、栈分配、静态存储分配

栈分配:有OS(操作系统)负责自动分配及释放,存放函数的参数值、局部变量等

堆分配:用户程序手动申请和释放的,如C中malloc函数、C++及Java中new。优点是设置的变量由程序自行决定,使用灵活。但分配后要及时释放,否则会导致内存泄露。一般向Java、python都可以自动回收不在使用的变量,类似空引用等。

静态储存分配:即全局变量,整个程序运行期间都存在,知道程序结束才释放

堆和栈的比较

​ 通俗来说,堆主要来存数据,栈来执行程序。这种不同主要由各自的特点决定的:

:在C/C++中,方法调用通过栈进行,局部变量、形参都从栈中分配内存。方法执行完毕后,退出函数时栈的内容便被销毁。要注意的是,为要执行的方法分配栈内存时,需要事先知道数据区的大小,虽然分配在运行时进行,但分配的大小是确定的,这个大小是在编译时确定,而非运行时

:程序运行时请求系统分配给自己内存,由于系统管理内存的分配,所以分配和销毁都要占用时间,导致堆的效率较低。优点在于,编译器不必事先知道分配多少空间,也不必知道数据要保存多长时间,用堆存数据时自主性较高。面向对象的多态性,恰恰是堆的特性的运用,因为多态变量的所需空间只有运行时创建对象后才能确定。

JVM下的堆栈

​ JVM是基于栈的VM,JVM会为每个新创建的线程都分配栈,它的运行就是通过对栈的操作完成的。栈以帧为单位保存线程状态,对栈仅有两种操作:以帧为单位的压栈和出栈操作。某线程正在执行的方法称为此线程的当前方法,帧也同理。当线程激活一个方法,JVM会进行压栈,而这一帧就是当前帧。方法执行期间,栈用来保存参数、局部变量、中间计算过程及其他数据。栈具有先进后出的特性。

​ 每个Java应用对应一个JVM,每个JVM对应一个堆。程序运行中创建的所有类实例都在该堆中,由所有线程共享。Java中分配内存是自动初始化的。对象的存储空间在堆中分配,该对象的引用在栈中分配,也就是说建立一个对象同时从两处分配空间,堆具有先进先出的特性。

Java中的堆栈

​ 栈:函数中的基本类型和引用变量在栈内存中分配,若超出函数作用域后,Java会自动释放调该作用域的内存空间,并为做他用

​ 堆:存放由new创建的对象或数组,分配的内存由JVM的垃圾回收器管理。

总结:堆是运行数据区,不需要代码显式释放,优势是可以动态分配内存大小,生存期也不必明确。缺点是运行时动态分配,速度较慢。栈存取速度比堆快,仅次于寄存器,数据共享。缺点是不灵活,内存大小和存活时间都要明确

参考文章

Java中堆和栈

Java中堆内存和栈内存详解

彻底理解Java中堆和栈

posted @ 2022-04-12 10:05  lifelikeplay  阅读(29)  评论(0编辑  收藏  举报