Java内存区域——Java虚拟机栈

 

Java虚拟机栈这块区域的功能,描述的是Java方法执行动态内存模型。就是说,一个方法的执行以及执行完毕,那么,整个的内存模型就是在Java虚拟机栈中。

每个方法执行都会创建一个栈帧,伴随着方法从创建到执行完成。栈帧是用于存储方法可执行的局部变量表、操作数栈、动态链接,方法出口等。每次方法执行,栈帧都会伴随着一个进栈以及出栈的这么一个过程。我们可以简单的描述一下这个过程,这是我们的Java虚拟机栈

栈内存是一端开口,先进后出的原则,每一个方法要执行,首先要创建一个栈帧

每一个方法执行都要创建一个栈帧,那么,这个栈帧里面所存储的就是局部变量表、操作数栈、动态链接、方法出口等,我们创建好了栈帧之后,方法就开始进栈,进栈就开始执行,那么,在执行的过程中,比如说它调用了另外的方法,那么,另外这个方法也需要创建一个栈帧,接着,它所调用的那个方法进栈

那么,这个方法就开始执行了,那么,这个方法执行到方法出口之后,这个方法就执行完毕了,方法执行完毕之后,这个栈帧就出栈了,出栈之后就销毁了

然后接着执行它

那么,这个方法继续执行,一直执行完毕,出栈

这就是一个方法执行的过程。也就是说,Java虚拟机栈描述的就是Java方法执行的动态内存模型。

什么是局部变量表呢?

局部变量表所需的内存空间其实是在编译期就完成了分配,当进入到一个方法的时候,这个方法需要在栈中分配多少内存其实是固定了的,那么在方法运行期间,这个内存大小是不会改变的。

大家这里可能有疑问了,比如引用类型,比如我们这里有一个User对象,这个对象里面有一个name属性,那么,我们在运行期间可能给这个name指定值

这个name属性是String类型

我们可能会给name这个属性指定值,那么,name属性值的长度肯定是不固定的,那么这个时候,它的内存区域是不会变化的吗?为什么在方法运行期间是不会改变局部变量表的大小?其实,我们在局部变量表中所引用的只是一个对象的引用,后面会讲,对象的创建会创建到堆内存中,而局部变量表所存储的是一个对象的引用,那么,这个对象的引用,这个大小是不会改变的,所以,在方法运行期间局部变量表的大小是不会改变的

接下来我们说一下Java虚拟机栈的大小的问题。

如果虚拟机栈放不下栈帧了怎么办?即虚拟机栈中放满了栈,但是依然去调用方法,这个时候,我们就遇到了我们所熟悉的StackOverFlowError,这叫栈内存溢出,这个异常其实是我们如果写一个递归调用的方法,就非常常见这个异常。我们来模拟一下栈内存溢出,我们知道每一个方法的执行都会进栈

我们通过内存模型来分析一下这个报错的原因,首先有一个Java虚拟机栈

首先

调用tes()方法,tes()方法进栈

这个方法进栈之后,首先执行第六行代码,然后接着执行第七行代码,执行第七行代码的时候,Java虚拟机发现又执行了一个方法,接着这个方法又进栈,所以,不停的进栈,方法之间不停的调用,不停的进栈,那么,我们就会发现

栈内存就会出现溢出的问题,那么,也就导致了StackOverflowError这个异常的抛出。如果我们把这个栈的大小改成非常大,就是,我们不限定这个栈的深度的大小,那么,这个时候它会不停的去申请,如果不限定栈大小的话,如果当栈的内存区域已经大于Java虚拟机设定的内存,或者说,已经超出了我们机器本身的内存,已经申请不下来内存的时候,就会抛出OutofmemeryError,就是内存溢出。

 

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值