JVM学习03:运行时数据区域-JAVA虚拟机栈

时间:2022-12-29 09:52:17

JVM学习03:运行时数据区域-JAVA虚拟机栈

基本描述

与程序计数器一样,JAVA虚拟机栈也是线程私有,并且生命周期与线程相同。
由于虚拟机栈描述的是Java方法执行的内存模型,所以虚拟机栈主要存储的是方法相关的内容(方法参数、局部变量、返回值等);

实现方式

实现方式当线程Thread1启动时,会在Java Stack中分配一块区域,用来存储需要执行相关方法的信息,当线程调用某个方法使,会同时创建一个栈帧(用于存储局部变量、操作栈、动态链接、方法出口等信息),并且根据对应类的类信息获取此方法的局部变量区和操作数栈的大小(编译期大小就确定),并据此分配栈帧的内存,然后压入Java栈中,如下图所示:
JVM学习03:运行时数据区域-JAVA虚拟机栈
栈帧由三部分组成:局部变量表、操作数栈和帧数据区。

局部变量表:存放局部变量和方法参数

局部变量表存放了编译器可知的各种基本数据类型(boolean、byte、char、short、int、float、long、double)、对象引用(Objectreference)和字节码指令地址(returnAddress类型)。其中64位长度的long和double类型的数据会占用2个局部变量空间(Slot),其余的数据类型只占用1个。【线程同步问题】
索引说明:按照索引的方式访问变量表,索引范围从0-最大Slot数量
32位数据类型变量:索引n代表低n个Slot
64位数据类型变量:索引n代表第n和n+1两个Slot
实例方法索引0默认为实例对象的应用(this),从1开始存储参数列表、方法内部变量、作用域。
可重用性:局部变量表中的Slot是可重用的,方法体中定义的变量,作用域并不一定会覆盖整个方法体,如果当前字节码PC计数器的值已经超过了某个变量的作用域,那么这个变量对应的Slot就可以交给其他变量使用。

这样的设计不仅仅是为了节省空间,在某些情况下Slot的复用会直接影响到系统的而垃圾收集行为。

操作数栈:线程的工作区,用来存放运算过程中的临时数据

帧数据区:保存支持常量解析、正常方法返回以及异常派发机制的数据

后续的博客中会对栈帧做详细的说明与讲解。

异常

异常:
在JVM规范中,对这个区域规定了两种异常情况:

如果线程请求的栈深度大于JVM允许的深度,抛出*Error
如果虚拟机栈可以动态扩展(目前大部分JVM都可动态扩展),当扩展时无法申请到足够的内存时,会抛出OutOfMemoryError异常 。

If the computation in a thread requires a larger Java stack or native method stack than is permitted, the Java virtual machine throws a *Error in Oracle JVM, OutOfMemoryError in IBM JVM, using –Xss to set the maximum stack size.
The default is 256 KB for 32-bit JVMs and 512 KB for 64-bit JVMs.