一、栈基础
1.位置
2.几个特点
- 吃多了吐就是栈,吃多了拉就是队列。
- (重点)栈存在生命周期,正在运行的永远在最上面,用完就弹出,如main()也弹出了,栈就销毁,内存释放
3.(重点)栈中储存的数据
- 八大基本数据类型
- 对象引用的地址
- (举例??)实例的方法.
二、栈帧
1。定义
栈帧(Stack Frame)栈空间的 基本元素,用于 方法的调用和方法的执行的数据结构
2. 包含了什么?
栈帧储存了
- 1.方法的局部变量表
- 2.操作数栈
- 3.动态链接
- 4.方法放回地址
3.栈帧和方法的关系
每一个方法的执行都对应了一个栈帧入栈到出栈的过程。
4.什么时候分配栈帧的内存?分配多少内存?
在编译代码的时候栈帧中需要多大的局部变量表,多深的操作数据栈都已经完全确定了,因此一个栈帧需要分配多少内存,不会受程序运行期数据的影响,只取决于虚拟机的实现。
三、栈帧都包含了什么详解:
1. 局部变量表(Local variable Table)
1.主要关注的栈内存,就是JVM栈中的局部变量表的部分。
2.定义:局部变量表(Local variable Table)是一组储值空间,用于存放方法参数和方法的内部定义的局部变量,并且在Java编译为.class文件的时候就分配了该方法所需要的局部变量表的最大容量.
3.变量槽(Variable Slot)
(1)定义:是局部变量表容量的最小单位 4字节 32 位长度(4*8),
(2)储值内容:blloean ,byte ,char short,int float ,【refrence】,double 和 long 8字节型需要2个Slot空间.
(3)【reference】引用地址:一般来说虚拟机都能从直接引用或者间接引用中查找对象一下2点
- 在堆区存放的数据的开始索引
- 数据类型在方法区的数据类型
4.实例
方法执行时候,虚拟机使用局部变量表完成参数的传递,如果执行的方法是实例对象的方法,局部变量的0索引(比如x00001)就是在堆区对象实例的引用(通过this可以访问到这个地址)
其他参数按照顺序排列。
5.Slot复用
为了节省空间,Slot是可以复用的,也就是PC计数器的指令指已经超出了某个变量的作用域,(执行完毕)那么这个变量对应的Slot就会给其他变量使用,
- 优点:节省栈帧空间
- 缺点:影响垃圾回收:如果有大方法占用比较多的Slot,然后又不及时清除,或者设置为null,垃圾回收器就不能回收该内存.
2.动态连接(Dynamic Link)
每个帧都包含一个指向运行时常量池中该帧所属于方法的引用,持有这个引用是为了支付方法调用过程中的动态连接。
- 静态解析:在类的加载的阶段的解析2.3阶段会将符号(PI)转化为直接引用(0x001),这种转化也成为静态解析。
- 动态连接:另外一部分,在每次运行的时候将符号转化为直接引用,这部分称之为动态连接
3.方法返回地址(父帧)
1.执行方法返回的2种方法:
- 1.正常退出:执行到return ,就退出方法
- 2.异常退出:发生异常且未处理,
2.无论采用 哪一种方法,在退出后都需要返回之前方法调用的位置,就是父帧
一般来说,方法正常退出时候,PC计数器的值可以作为放回的地址,栈帧中会保存这个计数器中的值,但是方法异常退出时候,返回的地址通过异常处理器表来确定的,栈帧中一般不会保存这部分的信息。
操作数栈:
1.操作数栈 和 局部变量表一致
- 编译为class就确定大小
- Slot为基础储存单位
- 、
2.作用:当一个方法开始时候,方法数栈始空的,执行中,各种字节码文件指令往操作数栈中读取内容和写入内容,入栈和出栈的操作
比如算术运算就是通过操作数栈来进行的,或者调用其他方法时候是用操作数栈来传递参数的
四、栈溢出模拟 SO(StackOverflowError)
public class Demo {
public static void main(String[] args) {
new Demo().a();
}
private void a(){
b();
}
private void b(){
a();
}
}
Run:
Exception in thread “main” java.lang.StackOverflowError