Java运行时栈帧结构

栈帧也叫过程活动记录,是编译器用来进行方法调用和方法执行的一种数据结构,它是虚拟机运行时数据区域中的虚拟机栈的栈元素,栈帧中包括了局部变量表,操作数栈,动态连接和方法返回地址以及额外的一些附加信息,在编译过程中,局部变量表的大小已经确定,操作数栈深度也已经确定,因此栈帧在运行的过程中需要分配多大的内存是固定的,不受运行时影响,对于没有发生逃逸的对象也会在栈上分配内存,对象的大小其实在运行时也是确定的,因此即使出现了栈上内存分配,也不会导致栈帧改变大小。

一个线程中,可能调用链会很长,很多方法都同时处于执行状态。对于执行引擎来讲,活动线程中,只有栈顶的栈帧是最有效的,称为当前栈帧,这个栈帧所关联的方法称为当前方法。执行引擎所运行的字节码指令仅对当前栈帧进行操作。

运行时栈帧结构

  1. 局部变量表
    是一组变量值的存储空间,用来存储方法参数和方法内部定义的局部变量,而类变量和常量存放在方法区中。

    局部变量表的最小单元是slot(变量槽),如在32位操作系统中,slot大小一般为32位,而double和long是64位的,需要两个slot存储,那么使用两个slot进行读取和写入是否会有线程安全性问题呢?
    答:这是一个非原子性操作,需要分别读取和拼接,而虚拟机栈是处于线程独占区,不会出现线程安全问题。

    引用数据类型变量也是占32位的。

    出现线程安全问题必备的三要素是: 1、多线程    2、有共享资源     3、对共享资源进行非原子性操作

    slot变量槽是可以复用的,为了降低内存的开销,但对垃圾回收有一定影响。当一个变量的pc寄存器的值大于slot的作用域的时候,slot是可以复用的。

     
  2. 操作数栈
    Java虚拟机的解释执行引擎被称为"基于栈的执行引擎",其中所指的栈就是操作数栈。
    操作数栈也常被称为操作栈。和局部变量表一样,操作数栈也是被组织成一个以字长为单位的数组。但是和前者不同的是,它不是通过索引来访问的,而是通过标准的栈操作——压栈和出栈来访问的。比如,如果某个指令把一个值压入到操作数栈中,稍后另一个指令就可以弹出这个值来使用。

    虚拟机在操作数栈中存储的数据的方式和局部变量表中是一样的:如int、long、float、double、reference的存储。对于byte、short以及char类型的值在压入到操作数栈之前,也会被转换成int。
     
  3. 动态连接
    Java方法调用分类
     
  4. 方法返回地址
    方法调用时通过一个指向方法的指针指向方法的地址,方法返回时将回归到调用处,那个地方是返回地址。
    方法返回地址获取分为正常退出和异常退出
    正常退出:通过pc寄存器值获取
    异常退出:通过异常处理器表确定返回地址
     
  5. 附加信息
    虚拟机规范中允许具体的虚拟机实现增加一些规范中没有描述的信息到栈帧中。这部分信息完全取决于虚拟机的实现

猜你喜欢

转载自blog.csdn.net/itcats_cn/article/details/81142689