您的位置 首页 java

Java堆和栈你敢说了解吗?看完这个文章再有底气说吧

JAVA,内存模型中堆和栈的区别

在了解Java堆和栈的区别之前,我们先了解一下内存分配策略。

JAVA内存模型中堆和栈的区别——内存分配策略

程序运行时有三种内存分配策略—— 静态,栈式,堆式

静态存储:在编译时就能确定每个数据目标,在运行时的存储空间需求,因而在编译时就可以给他们分配固定的内存空间,这种分配策略要求程序代码中不允许有可变数据结构的存在,也不允许有嵌套或者递归的结构出现,因为它们都会导致编译程序无法计算程序的存储空间。

栈式分配 该分配可称为动态的存储分配,是由一个类似于堆栈的运行栈来实现的,和静态存储的分配方式相反,在栈式存储方案中,程序对数据区的要求在编译时是完全未知的,只有到了程序运行时才能知道,但是规定在运行中进入一个程序模块时,必须知道该程序模块所需数据区的大小才能分配其内存和我们在数据结构中所熟知的栈一样,栈式存储按照先进后出的原则进行分配。

堆式存储:专门负责在编译时或运行时模块入口处都无法确定的内存分配,比如可变长度串和对象实例堆有大片的可利用空间或空闲块组成,堆中内存可按照任意顺序分配和释放。

JAVA内存模型中,堆和栈的区别和联系

联系:创建好的数组和对象实例都会保存在堆中,想要引用堆中的某个对象或者数组,我们可以在栈中定义一个特殊的变量,让栈中这个变量的取值等于数组或对象在堆内存中的首地址,栈中这个变量就成了数组或对象的引用变量,就可以用栈中引用变量访问堆中的数组或对象,引用变量就相当于为数组或对象起的一个名称,引用变量是普通的变量定义,是在栈中分配引用变量,在程序运行到其他作用域外时,就会被释放掉,而数组和对象本身在堆中分配及时程序运行到使用new产生数组或对象的语句所在的代码块之外,数组本身和对象所占据的内存不会被释放,他们在没有引用变量指向时,才会变为垃圾,需要等待随后一个不确定的时间被GC释放掉。

调用new Person()时会在堆中创建相关对象实例,同时将其首地址赋值给p,并保存在了当前 线程 虚拟机栈内存中,栈通过获取变量p已保存的对象实例的地址,便能轻松调用到保存在堆中Person对象的实例。

主要区别体现在以下五个方面

①管理方式: JVM 自己可以根据针对内存栈进行管理操作,而且该内存空间的释放是编译器就可以操作的内容,而堆内存在JAVA中,JVM本身执行不会对其进行释放操作,而是让GC进行自动回收。

②空间大小:一般情况下栈空间相对于堆空间较小,这是由栈空间里存储的数据,以及本身需要的数据特性决定的,而堆空间在JVM堆实例进行分配时,一般大小都比较大。因为堆空间在JAVA程序中需要存储较多的JAVA对象数据。

③碎片相关:针对堆空间而言,即使GC能够进行自动堆内存回收,但堆空间活动量相对栈空间而言比较大,很有可能存在长期堆空间分配和释放操作,而且GC不是实时的,它有可能使堆中内存碎片逐渐积累起来,针对栈空间而言,它本身就是堆栈的数据结构,它的操作都是一一对应的,而且每一个最小单位的结构栈帧和堆空间内复杂的内存结构不一样,所以它在使用过程中很少出现内存碎片。

分配方式:一般栈空间有两种分配方式,静态分配和动态分配,静态分配是本身由编译器分配好了,而动态分配可能根据情况有所不同,而堆空间却是完全的动态分配的,是一个运行时级别的内存,而栈空间分配的内存,不需要我们考虑释放的问题,对空间即使在有GC的前提下,还是要考虑其释放问题。

效率:因为内存本身快的排列就是一个典型的堆栈结构,所以栈比堆效率高很多,而且计算机底层基本内存结构使用堆栈结构,使得栈空间和底层结构更加符合,操作也简单,只涉及到了最简单操作,入栈和出栈,栈针对堆的弱点是灵活程度不够,特别在动态管理时。堆最大优点在于动态分配,因为他在计算机底层实现可能是一个双向链表结构,所以在管理内存时操作比栈空间复杂很多,自然灵活度就高了,但这样的设计使得堆空间不如栈空间,而且要低很多。

总结:Java堆和栈结构在面试过程中也是常考点之一,也是工作中经常遇到问题的地方,所以我们应该重点去掌握如何去深入理解这些知识,更好的去使用它。

大家有什么问题也可以一起留言探讨。欢迎转发和关注~

文章来源:智云一二三科技

文章标题:Java堆和栈你敢说了解吗?看完这个文章再有底气说吧

文章地址:https://www.zhihuclub.com/184240.shtml

关于作者: 智云科技

热门文章

网站地图