JVM学习笔记——栈区
栈区 Stack Area
栈是运行时的单位,堆是存储单位,栈解决程序的运行问题,即程序如何执行,如何处理数据。
每个线程在创建时都创建一个该线程私有的虚拟机栈,每个栈里有许多栈帧,一个栈帧对应一个 Java 方法。
栈的特点:
-
每个栈与它所对应的线程生命周期保持一致
-
栈主管 Java 程序运行,保存方法的局部变量,部分结果,参与方法的调用与返回
-
JVM 对栈的操作只有两种,方法执行入栈和执行结束出栈
-
栈的访问快速有效,访问速度仅次于程序计数器
-
对栈来说不存在垃圾回收问题
栈帧
栈区中的一个栈对应一个线程,栈中的一个栈帧对应一个方法,在栈帧中封装了方法执行的局部变量表、操作数栈、返回地址、动态链接以及一些附加信息,如对程序调优调试信息等。
在活动的线程中,只有当前正在执行的方法才是有效的,因此该方法对应的栈顶栈帧称为当前栈帧,该方法称为当前方法,定义该方法的类为当前类。
执行引擎所有的字节码指令只针对当前栈帧进行操作。
如图所示,正在执行的线程所对应的当前线程中,栈帧1 对应的 方法1 调用了 栈帧2 对应的 方法2,方法2 又调用了 方法3,因此当前栈帧入栈。每个栈帧都存有所对应方法的各种信息。当正在执行的 方法3 执行完毕后,当前栈帧把执行结果返回给 栈帧2,当前栈帧出栈,栈帧2 变为当前栈帧,当 栈帧1 也出栈时,该线程执行完毕,执行其他线程。

局部变量表
局部变量表也称为局部变量数组或本地变量表。
局部变量表本质上是一个数字数组,主要用于存储方法参数和定义在方法内的局部变量。
-
局部变量表建立在线程私有的栈中,是线程私有数据,不存在安全问题
-
局部变量表所需的容量大小,在编译器就确定下来,在方法运行期不会改变其大小
-
方法嵌套调用的次数由栈的大小决定
-
局部变量表的变量只在当前方法调用中有效,方法调用结束后,方法栈帧销毁,局部变量表随之销毁
操作数栈
操作数栈也成为了表达式栈。
操作数栈主要用于保存计算过程的中间结果,同时作为计算过程中变量临时的储存空间。
-
栈中的任何一个元素可以是任意的 Java 数据类型
-
操作数栈只能通过标准的入栈出栈操作来完成数据访问,不支持索引
-
如果被调用方法带有返回值,返回值会被压入当前栈帧的操作数栈中,并更新程序计数器的下一条指令
动态链接
每个栈帧内部包含一个指向运行时常量池中该栈帧所属方法的引用,这个引用的目的就是为了支持当前方法的代码实现动态链接。
动态链接的作用就是为了将符号引用转换为方法的直接引用,当一个方法调用其他方法时,就通过常量池中指向方法的符号引用完成。
方法返回地址
当一个方法被执行后,有两种方式退出这个方法。
正常完成出口:执行引擎遇到任意一个方法返回的字节码指令,产生返回值传递给上层的方法调用者。
异常完成出口:在方法执行过程中遇到了异常,并且这个异常没有在方法体内得到处理,只要在本方法的异常表中没有搜索到匹配的异常处理器,就会导致方法退出。异常完成出口的方式退出,不会给它的调用者产生任何返回值。
无论采用何种方式退出,在方法退出之前,都需要返回到方法被调用的位置,程序才能继续执行,方法返回时可能需要在栈帧中保存一些信息,用来帮助恢复它的上层方法的执行状态。

浙公网安备 33010602011771号