一、栈基础

1.位置

Java默认调用栈大小_Java默认调用栈大小

2.几个特点
  1. 吃多了吐就是栈,吃多了拉就是队列。
  2. (重点)栈存在生命周期,正在运行的永远在最上面,用完就弹出,如main()也弹出了,栈就销毁,内存释放
3.(重点)栈中储存的数据
  1. 八大基本数据类型
  2. 对象引用的地址
  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