• JVM之栈空间


    JVM之栈空间

    Java虚拟机内存区域模型

    **黄色区域:**所有线程共享的内存区域,会存在垃圾回收。

    **灰色区域:**线程私有不会产生垃圾回收。

    栈空间是运行时数据区中的一部分,那么栈空间如何存储数据呢?

    Java虚拟机栈是什么

    在运行时数据区中JAVA栈、本地方法栈、程序计数器三个都是线程所私有,栈的生命周期和线程的生命周期是一样的同生共死,虚拟机栈描述的是Java方法执行的内存模型,每个方法在执行的同时都会创建一个栈帧,用于存储局部变量表、操作数栈、动态链接、方法出口等信息,每个方法从调用直至执行完成的过程,就对应着一个栈帧在虚拟机中入栈到出栈的过程。

    需要注意的是在Java虚拟机规范中,对栈空间规定了两种异常情况

    • 如果线程请求的栈深度大于虚拟机所允许的深度,将抛出StackOverflowError异常。

    • 如果虚拟机栈可以动态扩展(当前大部分的Java虚拟机都可动态扩展,只不过Java虚拟机规范也允许固定长度的虚拟机栈)。如果扩展时无法申请到足够的内存,就会抛出OutOfMemoryError异常

    栈帧如何使用

    一个方法从调用到结束就意味着一个栈帧从栈中入栈到出栈的过程,那么具体怎么做呢?参考如下代码

    public class App {
        private String name;
        private Object object = new Object();
    
        public int add() {
            int a = 2;
            int b = 3;
            int c = (a + b) * 8;
            return c;
        }
        
        /**
         * 程序入口
         */
        public static void main(String[] args) throws InterruptedException {
            App app = new App();
            int result = app.add();
            System.out.println(result);
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    我们可以查看App.class编译后的文件,javap -c App.class得到结果,如add方法的字节码如下

      public int add();
        Code:
           0: iconst_2
           1: istore_1
           2: iconst_3
           3: istore_2
           4: iload_1
           5: iload_2
           6: iadd
           7: bipush        8
           9: imul
          10: istore_3
          11: iload_3
          12: ireturn
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    iconst_2:表示将数值2压入操作数栈中

    istore_1:表示将操作数栈的栈顶出栈,放入局部变量表索引为1的位置(也就是给变量a赋值,当然先要在局部变量表中分配内存)

    iconst_3和istore_2就类似了,执行完结果如下所示

    iload_1:把局部变量表索引为1的值(也就是变量a的值)放入操作数栈栈顶,iload_2类似,执行完结果如下所示

    iadd:将操作数栈栈顶元素和栈顶下一个元素进行加法运算,运算后放入操作数栈栈顶

    bipush 8:将一个八位带符号整数压入操作数栈中

    imul:乘法计算,类似上面的加法将操作数栈的栈顶元素和栈顶下一个元素出栈,然后将结果入栈到操作数栈中

    istore_3:将操作数栈的栈顶元素出栈,放入局部变量表索引为3的位置(就是为变量c赋值)

    iload_3:将局部变量表索引为3的值(也就是变量c的值)放入操作数栈栈顶

    ireturn:返回操作数栈栈顶元素也就是40

    到这里add方法就结束了返回,方法出口记录应该返回的位置,也就是add方法栈帧出栈,然后进入main方法栈帧执行逻辑,所以整体逻辑如下所示。
    在这里插入图片描述

    注意

    在活动的线程中,只有位于栈顶的栈帧才是有效的,称之为当前栈帧,与这个栈帧相关联的方法称为当前方法。

    执行引擎的所有字节码指令都只针对当前栈帧进行操作。

  • 相关阅读:
    还有医学生不知道这个免费好用的在线样本量计算器吗?
    SSH远程登录:两台或多台服务器之间免密登录设置
    Docker 入门看这一篇就够了,万字详解!
    CSS-clamp 函数说明
    Go 语言中的 Moduels 管理(Let‘s Go 三十四)
    【初阶数据结构】——带头双向循环链表(C描述)
    LeetCode每日一题——808. 分汤
    【FreeRTOS】【STM32】03 FreeRTOSConfig.h头文件简介与修改
    day51
    隆化的大米排之首 国稻种芯·中国水稻节:河北承德十大特产
  • 原文地址:https://blog.csdn.net/zzf1233/article/details/125531771