Java虚拟机栈的出栈入栈流程及栈内存大小设置

83 篇文章 9 订阅
12 篇文章 1 订阅

前言

Java虚拟机栈(Java Virtual Machine Stacks)是线程私有的,即生命周期和线程相同。

Java虚拟机栈和线程同时创建,用于存储栈帧。每个方法在执行时都会创建一个栈帧(Stack Frame),用于存储局部变量表、操作数栈、动态链接、方法出口等信息。每一个方法从调用直到执行完成的过程就对应着一个栈帧在虚拟机栈中从入栈到出栈的过程。虚拟机栈结构示意图如下:

image-20210731105926589

我们来了解下出栈入栈的过程及虚拟机栈的参数设置。

出栈入栈过程

我们来通过一个实例来看下jvm中虚拟机栈的调用情况。

代码示例

先看下面的代码:

package com.example.test;


public class StackDemo {
    public static void main(String[] args) {
        System.out.println("main 方法start");

        StackDemo stackDemo = new StackDemo();
        stackDemo.methodA();

        System.out.println("main 方法end");
    }

    public void methodA(){
        System.out.println("methodA start");
        methodB();
        System.out.println("methodA end");
    }

    public void methodB(){
        System.out.println("methodB start");
        methodC();
        System.out.println("methodB end");
    }

    public void methodC(){
        System.out.println("methodC start");
        System.out.println("methodC end");
    }
}

说明:上述代码中main()调用methodA(),methodA()调用methodB(),methodB()调用methodC()。

具体步骤

我们在idea中通过debug模式来查看它的栈帧情况:

第一步,先执行main方法,main方法入栈:

image-20210731100920426

第二步,执行到第15行,进入到methodA()方法,methodA()方法入栈:

image-20210731101143950

第三步,执行到第22行,进入到methodB()方法,methodB()方法入栈:

image-20210731101511230

第四步,执行到第28行,进入methodC()方法,methodC()方法入栈:

image-20210731101644378

到目前为止,栈中的栈帧情况如下:

image-20210731101809851

栈底部是main方法,上面依次是methodA,methodB,methodC。

第五步,然后继续往下执行,methodC执行完毕,栈情况如下:

image-20210731102033080

可以看到methodC方法执行完毕后,methodC出栈,回到methodB方法中的下一行继续执行。

第六步,methodB执行完毕,methodB出栈,如下:

image-20210731102214205

此时栈中只剩下methodA和main方法。

第七步,methodA执行完毕,methodA出栈:

image-20210731102340017

此时只剩下main方法在栈中。

第八步,main方法执行完毕,栈中数据全部出栈:

image-20210731102600319

到此,整个main方法执行结束。

设置虚拟机栈的大小

参数设置

-Xss 为jvm启动的每个线程分配的内存大小,默认JDK1.4中是256K,JDK1.5+中是1M

-Xss1m
-Xss1024k
-Xss1048576

代码实例

我们通过一个代码案例来看动态设置虚拟机栈的大小:

public class StackDemo {
    static long count=0;
    public static void main(String[] args) {
        count++;
        System.out.println(count);
        main(args);
    }
}

这是一个无限递归的方法,不管虚拟机栈设置多大,它总会栈溢出的。我们通过一个count的值来记录不同虚拟机栈大小下的栈溢出的情况。

我本地默认情况下的运行结果:

image-20210731111756553

count达到8641后栈溢出。

然后我们在idea里面设置虚拟机栈的大小,设置为256k:

步骤如下:

image-20210731112116219

image-20210731111901561

由于256k比默认的1m要小很多,所以虚拟机栈应该会更快的溢出。

接下来我们进行验证:

image-20210731112358725

可以看到,count到2192的时候就已经溢出了,符合我们的预期,说明参数设置有效。

总结

我们通过一个代码实例一步步的debug来观察了虚拟机栈的情况,从而对方法执行中的栈帧出栈入栈有了更清晰的认识。用-Xss参数对虚拟机栈的大小进行了设置,观察了设置后的效果。

  • 3
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

程序员资料站

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值