java 堆栈内存深入了解

【 前言】

前面我们学习了java的基本类型和引用类型​,我们继续深入了解下 java堆栈内存结构。

【 java内存结构 】

那么,就有人问了,基本类型和引用类型有啥区别,啥是引用类型,这就有很大学问了,顺便也扯上了变量内存结构了。变量声明就是一个内存空间的开辟,那这些内存空间在哪呢?

首先了解一下java内存结构:JVM分了5片内存:
1、程序计数器:记录程序执行到哪一个指令
2、本地方法栈:与虚拟机栈功能相似,不过虚拟机栈为java方法服务,本地方法栈为Native方法服务
3、方法区:存放字节码,常量 ,静态变量,是一个共享的区域
4、虚拟机栈:执行方法其实就是栈帧入栈,出栈的过程,因为是跟方法有关的,而且局部变量常常在方法中,所以栈存储的是局部变量
5、堆:存放引用类型,成员变量
在这里插入图片描述

我们接触最多的是堆和栈(虚拟机栈),这里一定要注意这两个的区别。

(1)主要是存储方法帧的,每执行一个方法的时候,就会为该方法创建一个栈帧,使其入栈。然而局部变量一般随着方法生成而存在,所以局部变量存储在栈中。

(2)堆一般用来存放引用型对象,以及对应的成员变量,当对象创建时,会在堆中开辟一块地址,并给这个对象的成员变量使用。

【 java基本类型和引用类型区别 】

基本类型就是使用一个空间存储数。但注意:很多网上教程会说,基本类型是存在栈中,这是错误的,因为基本类型也分成员变量和局部变量,局部变量随着方法入栈就存在栈中,而成员变量会随着对象在堆中空间的开辟而存储在堆中。例如: int[] a=new int[]{1,2}; 由于new了一个对象,所以new int[]{1,2}这个对象时存储在堆中的,也就是说1,2这两个基本数据类型是存储在堆中。

引用类型就比较特别,引用类型占用两块内存,一个栈,一个堆, 栈中存放的是堆中的地址。啥意思?什么是引用类型?举个简单例子,一间房子,我可以在里面 放置家具,放完后用钥匙锁着,把钥匙放在抽屉里面,那我想找某个家具是不是通过钥匙来找到房间再进去找家具。从这个例子我们可以对应一下,房间就是内存堆开辟的空间,家具就是数 据,钥匙就相当于引用类型(堆中的地址),抽屉相当于栈,具体的数据放在堆上,引用类型放在栈上。例如:String s=new String(“hello world”),new出来的hello world是存放在堆中,并且将这个堆地址给栈中s来保存。

在这里插入图片描述

变量的作用域:
1、从定义上说,变量作用域到大括号结束,出了大括号就就不存在了
2、从内存上解释,一个类中什么时候有大括号的存在?只有两种情况,一个是类两端有大括号。

例如:public class Person{},还有是类里面的方法有大括号,例如:public void a(){}。先说类里面的方法,上面也说了,执行完这个函数就相当于出栈,那么局部变量也当然随着函数的结束而销毁,大括号等同于这个类或方法已经执行完了,也就是说作用域只在大括号内,出了大括号就意味着函数结束了,也就是出栈了,变量作用域就无效了。

同理,类两端里面是全局变量,执行到大括号也就是类被释放了,对应的全局变量也没了。举例如下:

在这里插入图片描述
在这里插入图片描述
上面方法执行流程为:
1、main方法的栈帧入栈,在main的帧当中有一个a= 20;
2、当执行show(a)时,此时传入了一个参数a= 20;执行show方法,show方法的栈帧入栈,第一次打印结果为a= 20,a改为50,再次打印 结果为:a = 50;
3、当执行完show方法后,show方法的栈帧就会出栈;
4、此时栈中只有一个main方法的栈帧,所以在执行完show方法后,再去打印a ,此时a = 20;

【 总结 】

1、这篇文章更多是强调变量对应的内存关系,详细了解堆栈,一定要明确好关系。
2、引用型基本上都是new出来的,string特别点,引用型new出来的内容放在堆上,地址存放在栈上。
3、基本类型也分成员变量和局部变量,局部变量随着方法入栈就存在栈中,而成员变量会随着对象在堆中空间的开辟而存储在堆中。
4、局部变量是存储在栈中,成员变量是存放在堆中(因为随着类的创建生成,类创建是在堆上)。

猜你喜欢

转载自blog.csdn.net/weixin_43423484/article/details/125691622