《JVM修仙之路》虚拟机栈还可以这么玩

《JVM修仙之路》嫩春鲦,谐音梗扣分

希望可以用一种有趣的方式和大家一起学习JVM,让我们觉得这些知识也没有这么难搞。

胡言乱语

书接上回,沿着大佬所看的方向,你只能看到一条条湍急的河流,还有拥有异常活力的鲦鱼。

你有点疑惑,看向大佬,所以是啥?

大佬转头说道,v50,不然不给说。
在这里插入图片描述
小王一脸黑线,但也没办法,忍着怒气转了过去。然后勉强挤出一个笑,现在可以了吧,告诉我原因吧。

大佬,指向下面的河流的鱼,说道此鱼名为嫩春鲦,只要吃下便可增加内力,但是和个人的体质有关,有的人每吃一条便可增长一部分的内力,有的人吃完一条之后就不会在增长内力。看你这样,也顶多一条完事了。

强挤出一声谢谢之后,小王就带着小美去捉鱼了。
在这里插入图片描述
在折腾了一下午之后,终于抓到了一只,烤熟之后小王给小美分了一半。在吃完之后,突然觉得体内一股暖流正在上升,这股暖流转而运行到腹部,便不再移动。你也学着他们的施法的姿势一样,但明显没啥作用。而反观隔壁的小美,已经带着这股劲耕了二里地了。

正在你觉得自己没法逆天改命的时候,一个白衣老者款款向你俩走来。

老者开口道,少年,好体制呀,吃完嫩春鲦之后居然没有任何变化,不亏是天选之人。看你天赋异禀,不如拜入我门下,我定当好好培养你。

就这样你和小美都拜入白衣老者的门下,白衣老者就暂时叫他大长老。

大长老教你的第一课就是如何运用自己的内力。大长老说道,在吃完嫩春鲦之后,你已经开发出了自己的虚拟机栈,每当你要释放技能时,就有一个虚拟机栈供该技能使用。并且为了释放技能的更加顺利,我们会将技能分成一个个的方法,每个方法又会在该虚拟机栈中,分配到一个栈帧的内力,专供这个方法使用。

看着小美一脸懵逼,你心里不禁暗自窃喜,这不就对应了虚拟机栈中的栈帧吗,每一个方法都对应一个栈帧,每个栈帧都存储该方法的参数,局部变量和返回值等信息。

大长老接着说道。其实方法就像秘籍一样,只是告诉你怎么技能释放的步骤,而技能释放时所操作的东西则存储在另一部分。

你看向长老,技能释放时所操作的东西是不是存放在堆中。
在这里插入图片描述

长老一脸诧异的看着你,转而笑道,没想到你年纪轻轻就有如此悟性,真是不错。

正如你所说,就是存储在堆中。我们称技能操作的东西为对象,例如技能中所释放的火焰就是对象,这些火焰也需要我们的内力来支撑,内力来源被我们称为堆。而让火焰以怎样的形式喷出,或是喷向何处,则是方法中所需要做的。

听完这些之后,你对自己更加自信了,你更加确信了这里的技能释放机制,就和jvm的内部结构一致。所谓一个技能就可以对应一个线程,方法则为该线程运行过程中调用的方法,调用方法时要在对应线程的虚拟机栈中申请一块栈帧,而方法中创建新对象则需要到堆中申请空间,正好与技能释放过程一一对应。

到这里,你也按捺不住激动的心情,就想试一试技能。大师看出你的想法,转而教授了你如何释放火焰。

只见,弹指间你的手心中出现了一团火焰,同时你也感应到了体内虚拟机栈的变化,你感应到了该技能对应的虚拟机栈,同时你察觉到了栈中压入了一个栈帧,同时你的火焰对象也在堆中申请了内力,待到火焰熄灭,你感受到了虚拟机栈中栈帧的弹出,并且堆中申请的内力也被换了回去。

你带着小美一直反复练习。但是一次出现一团火已经不能满足你了,但是你目前只会创造一团火的方法。这时你突然想到,我每次只开启一个方法,申请一个栈帧,是不是我可以同时开启多个方法,申请多个栈帧呢,想到这里你心中一喜,来试试吧。
在这里插入图片描述

随着手心中一团团火焰的出现,你越来越激动,想着自己真是个天才。但慢慢你就发现了不对,随着火焰的增多,你慢慢感到眩晕感,直到你突然倒在了地上。

大长老听到响声,立刻将你扶起,待你静坐一会,才慢慢苏醒。你艰难的看向大长老问道,我这是怎么了?

大长老说道,你太过急功近利了,一次性开启了多个火焰生成方法,导致了申请的栈帧过多,栈内存溢出了。

你不禁一笑,心中想到写了这么多程序,居然把递归忘记终止条件这件事给忘了。

大长老叫你去休息一会,你也只好作罢,同时也发现了一件事情,为什么火焰出现的速度这么慢呢,是否能提高些速度呢?

JVM内容

  • JVM的内存结构中有虚拟机栈,并且每一个线程都有一个独占的虚拟机栈。这就使得存储在虚拟机栈中的内容通常是线程安全的。
  • 每一个虚拟机栈中又存储了多个栈帧,线程执行的每一个方法都要申请一个栈帧,存储了方法的参数,局部变量以及返回值等信息。但若是局部变量被作为返回值返回了,或是多个方法使用了相同的对象作为参数,那就线程不安全了。
  • 当申请的栈帧过多时就会导致了虚拟机栈内存的溢出。
  • 垃圾回收并不管理栈中的内存

栈帧过多 java示例

public class test {
    
    
    public static void dg(int a) {
    
    
        System.out.println(a);
        dg(a + 1);
    }

    public static void main(String[] args) {
    
    
        dg(1);
    }

}

如上述代码进行无限制的递归,就会导致栈帧过多,内存溢出
在这里插入图片描述

作为我自己的笔记,同时也是博主自己的兴趣的,如果大佬喜欢这个风格,欢迎在下方点击点赞和收藏按钮,我也很希望能收到您的评论。

更多内容请关注JVM修仙之路专栏
》》JVM修仙之路专栏《《

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/qq_43627076/article/details/132498511