返回

JVM系列(七):虚拟机栈是干什么的?

后端

今天继续给大家分享JVM系列的相关知识,今天介绍一下虚拟机栈的介绍。

虚拟机栈

虚拟机栈(Virtual Machine Stack)是Java虚拟机运行时数据区中的一块内存空间,主要用于存放Java方法执行过程中的局部变量表、操作数栈、动态连接、方法出口等信息。它是Java虚拟机运行时数据区中的一个独立的内存空间,并且线程私有 ,也就是对每个线程来说都有一个虚拟机栈。

局部变量表

局部变量表是一个包含了编译期可知的各种基本数据类型(boolean、byte、char、short、int、float、long、double)、对象引用以及returnAddress类型(指向了一条字节码指令地址)的数组。局部变量表的长度由方法中定义的局部变量的个数所决定,如果需要定义为long或者double类型的局部变量,实际上在虚拟机栈中占用了两个连续的局部变量槽空间 。局部变量表是Java虚拟机从上往下分配的,从0开始编号,索引值可以用来快速访问局部变量。

操作数栈

操作数栈是一个后进先出的数据结构,主要用于存放计算过程中产生的各种中间结果、临时变量和从局部变量表中获取的变量。Java虚拟机执行引擎运行时,所有操作数都通过操作数栈进行存储,当执行一个方法时,其需要的参数会从局部变量表中push到操作数栈中,在需要时再pop出来,这使得Java虚拟机具有良好的可移植性。

动态连接

动态连接是一种运行期技术,它允许一个类的方法或者字段在编译时并不确定,而是在运行时动态的解析确定。Java虚拟机通过维护一个Symbol Table来完成动态连接,其中包含了类或接口的全限定名、修改标志、方法的数量、字段的数量、方法表、字段表等信息。

方法出口

方法出口是虚拟机栈中一个指向方法返回地址的引用。当一个方法执行完成后,需要返回其被调用的位置,此时虚拟机栈会将方法出口中的地址pop出来,然后跳转到该地址处继续执行。

虚拟机栈的实现

虚拟机栈的大小由JVM启动参数-Xss来控制,默认大小为256KB,并且可以通过修改该参数来调整大小。

栈帧

虚拟机栈中的每一个执行单元都称为栈帧(Stack Frame),它存储了一个方法执行所需的局部变量表、操作数栈、动态连接、方法出口等信息。当一个方法被调用时,虚拟机就会创建一个新的栈帧并将其压入虚拟机栈中,当方法执行完成后,该栈帧就会从虚拟机栈中弹出。

栈溢出

当虚拟机栈的深度超过了其允许的最大深度时,就会发生栈溢出。栈溢出通常是由递归调用或循环调用导致的,也可能是由于程序中的异常处理不当造成的。当发生栈溢出时,Java虚拟机会抛出java.lang.StackOverflowError异常。

栈回收

栈回收是指虚拟机栈中不再使用的栈帧的回收过程。当一个方法执行完成后,其对应的栈帧就会被回收。栈回收可以释放虚拟机栈中被占用的内存空间,防止内存泄漏。

总结

虚拟机栈是Java虚拟机运行时数据区中一个重要的组成部分,它用于存放方法执行过程中的各种信息。虚拟机栈的大小由JVM启动参数-Xss来控制,默认大小为256KB。当虚拟机栈的深度超过了其允许的最大深度时,就会发生栈溢出。栈回收是指虚拟机栈中不再使用的栈帧的回收过程,可以释放虚拟机栈中被占用的内存空间。