小白看完也能理解java中的堆和栈的概念和区别
2021/4/8 1:08:35
本文主要是介绍小白看完也能理解java中的堆和栈的概念和区别,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
任何软件在运行时,都需要在内存中开辟空间。Java程序也不例外,也需要在运行时开辟空间,而Java程序运行时基于Java虚拟机(Java Virtual Machine,下文简称JVM)上运行,并对其做了细致的划分,栈和堆就是JVM划分出来的内存区域。
JVM内存的划分有五个区域:
1、寄存器
2、本地方法区(native method)
3、方法区
4、栈
5、堆
我们重点说下栈和堆:
栈内存中存储的都是局部变量(定义在方法内的变量、循环结构(for、while、do...while)内定义的也是局部变量),要加载局部变量,必须先加载方法(函数),所以方法会先进栈,然后再加载局部变量,局部变量的生命周期仅在方法执行期间,方法执行完就离开了其作用域,内存就会被释放了(实际上不是立即释放的,由GC自己判断处理的)。因为局部变量的声明周期很短(仅存在于方法内),所以栈内存的更新速度很快。
堆内存:存储引用类型(除了八大基本类型byte、short、int、long、char、float、double、char以外的都是引用类型。注意数组和String也是引用类型!!)的属性等对象的信息。每个new出来的对象都有其在内存中唯一的内存地址,所以也会用到栈内存也会存储对象的内存地址。
下面画个图更好的解释说明下。
比如在main函数里定义一个数组,
int[] arr = new int[3];
那么这句代码在内存中里发生了什么呢?
主函数先进栈,在栈中定义一个变量arr,接下来为arr赋值,但是右边不是一个具体的值,而是一个对象。对象创建在堆里,在堆中通过new关键字开辟空间,内存在存储数据的时候都是通过地址来体现的,地址是一块连续的二进制,然后给这个实体分配一个内存地址。数组都有索引(下标),数组这个实体在堆内存产生之后每一个空间都回进行默认的初始化(堆内存的特点,未初始化的数据是不能用的,但是在堆里是可以用的,因为在堆里的数据会隐式初始化(根据数据类型赋对应的默认值),但是栈不会,因此局部变量要使用就必须手动赋值)。
那么,堆和栈又是怎么联系起来的呢?
我们刚刚说过了,初始化对象时会给这个对象分配一个唯一的内存地址,那么JVM就会把这个内存地址给了在栈中的arr,arr就通过这个地址指向了数组。所以arr想操作数组时,就要通过这个地址,而不是直接把整个实体都赋值给他。这种我们就不再叫他基本数据类型了,而是叫引用类型。称为arr引用了堆内存中的实体。(相当于c/c++中的指针,但是Java中是没有指针这个概念的。)
如果
int[] arr = null;
这句代码就是使得arr不做任何指向,null的作用就是取消引用数据类型的指向。
当一个实体没有任何引用数据类型执行时,它在堆内种不会被立即释放,而是被当做一个垃圾,在不定时被Java的自动回收机制处理掉(GC),而在(C/C++中需要程序员手动回收,如果不回收就会在内存中越堆越多,直到内存溢出OOM,所以某种意义上来说,Java的内存管理对程序员来说更友好)。
总结:
1、栈内存存储局部变量(在方法内的变量)中的基本数据类型和引用类型的地址值;堆中存储对象(new出来的)具体信息
2、栈内存的更新速度要快于堆内存,因为局部变量的生命周期都很短,只在方法作用域内生效,出了作用域就无效了。
3、栈内存存放的变量生命周期一旦结束就会被释放,而堆内存中存放的对象不定时回收,这取决于JVM的自动回收机制(GC)。
参考文章:https://blog.csdn.net/pt666/article/details/70876410/
这篇关于小白看完也能理解java中的堆和栈的概念和区别的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2024-06-26结对编程到底难不难?答案在这里
- 2024-06-19《2023版Java工程师》课程升级公告
- 2024-06-15matplotlib作图不显示3D图,怎么办?
- 2024-06-1503-Loki 日志监控
- 2024-06-1504-让LLM理解知识 -Prompt
- 2024-06-05做软件测试需要懂代码吗?
- 2024-06-0514-ShardingSphere的分布式主键实现
- 2024-06-03为什么以及如何要进行架构设计权衡?
- 2024-05-31全网首发第二弹!软考2024年5月《软件设计师》真题+解析+答案!(11-20题)
- 2024-05-31全网首发!软考2024年5月《软件设计师》真题+解析+答案!(21-30题)