【无标题】-CSDN博客

48 阅读3分钟

栈帧的内部结构

局部变量表

  • 定义为一个数字数组,主要用于存储方法的参数和定义在定义在方法体内的局部变量,这些数据类型主要有基本数据类型,对象的引用,以及returnAddress类型
  • 由于局部变量表是建立在线程的栈上,是线程私有的数据,因此不存在数据安全问题
  • 局部变量表的大小是在编译器确定下来的,并且保存在Code属性的maxinum local variables数据项中,在方法运行期间是不会改变局部变量表的大小的
  • 参数的存放总是在局部变量数组的index0开始到数组长度-2的索引结束
  • 局部变量表最基本的存储单元是Slot(变量槽)
  • 如果当前帧是由构造方法或者实例方法创建的,那么该对象引用this将会放在index为0的solt处,其余参数按照参数表顺序排列
  • 局部变量表也是重要的垃圾回收根节点,只要在局部比那量表中直接或间接引用的对象都不会被回收

操作数栈(表达式栈)

  • 主要用于保存计算过程的结果,同时作为计算过程中变量的临时储存空间

  • 操作数栈就是jvm执行引擎的一个工作区,当一个方法开始执行的时候,一个新的栈帧也会随之被创建出来,这个方法的操作数栈是空的

  • 每一个操作数栈都会拥有一个明确的栈深度用于储存数值,其所需要的最大深度在编译时就定义好了,保存在方法的Code属性中名为max-stack的值

  • 栈中任何一个元素都可以是Java 中任意数据类型

    • 32bit的占用一个栈深度

    • 64bit的占两个

      操作数栈并非采用访问索引的方式来进行访问的,而是通过出栈和入栈的方式来完成的

  • 如果被调用的方法带有返回值的话,其返回值将会被压入当前栈帧的操作数栈中,并更新PC寄存器中下一条需要执行的字节码指令

  • 操作数栈中的元素类型必须与字节码指令严格匹配,这由编译器在编译期间进行验证,同时在类加载过程中的类型检验的数据分析阶段需要再次验证

动态链接(指向运行时常量池的方法引用)
  • 方法的返回地址

    • 存放该方法的pc寄存器的值

    • 一个方法的结束,有两种方式

      • 正常执行完成
      • 出现未处理的异常,非正常退出
    • 无论是通过哪种方法退出,在方法推出后都要返回到方法被调用的位置,方法非正常退出时,调用着的pc计数器的值作为返回地址,即调用该方法指令的下一条指令的地址,而通过一场退出的,返回地址是要通过异常表来确定,栈帧中一般不会保存这部分信息

  • 一些附加 的信息