对于每个线程,JVM在线程创建时创建一个单独的堆栈。Java 虚拟机堆栈的内存不需要是连续的。Java 虚拟机仅直接在Java堆栈上执行两个操作:推送和弹出帧。特定线程的堆栈可以称为运行时间堆栈. 该线程执行的每个方法调用都存储在相应的运行时堆栈中,包括参数、局部变量、中间计算和其他数据。完成一个方法后,从堆栈中删除相应的条目。完成所有方法调用后,堆栈变空,并且该空堆栈在终止线程之前被 JVM 销毁。存储在堆栈中的数据可用于相应的线程,而不能用于其余线程。因此我们可以说本地数据线程安全。堆栈中的每个条目称为Stack Frame或Activation Record。
栈帧基本上由三部分组成:局部变量数组、操作数栈和帧数据。当JVM调用一个Java方法中,首先它检查类的数据来确定的字的数量(局部变量阵列和操作数栈,其中大小是在字测量为每个单独的方法)的局部变量阵列中的该方法所需和操作数栈。它为调用的方法创建一个适当大小的堆栈帧,并将其推送到 Java 堆栈上。
1.局部变量数组(LVA):
堆栈帧的局部变量部分组织为从零开始的字数组。
它包含方法的所有参数和局部变量。
数组中的每个插槽或条目为 4 字节。
int、float 和reference 类型的值占据数组中的1 个条目或槽,即4 个字节。
double 和 long 的值占据数组中的 2 个连续条目,即总共 8 个字节。
字节,短,和char值将被转换为整数类型存放前和占用1个时隙即4个字节。
但是存储布尔值的方式因JVM而异。但是大多数 JVM 为局部变量数组中的布尔值提供了 1 个插槽。
参数首先按照声明的顺序放入局部变量数组中。
例如:让我们考虑一个类 Example 有一个方法自行车()然后局部变量数组将如下图所示:
// Class Declaration
class Example
{
public void bike(int i, long l, float f,
double d, Object o, byte b)
{
}
}
2. 操作数栈(OS):
JVM 使用操作数堆栈作为工作空间,就像粗略的工作,或者可以说是用于存储中间计算的结果。
操作数栈被组织成一个类似于局部变量数组的字数组。但这不是通过使用像局部变量数组这样的索引来访问的,而是通过一些可以将值推送到操作数堆栈的指令和一些可以从操作数堆栈中弹出值的指令以及一些可以执行所需操作的指令来访问。
例如:以下是 JVM 将如何使用以下代码,将包含两个 int 的两个局部变量相减并将 int 结果存储在第三个局部变量中:
因此,这里的前两条指令iload_0和iload_1将从局部变量数组中推送操作数堆栈中的值。指令isub将这两个值相减并将结果存储回操作数堆栈,在istore_2之后,结果将从操作数堆栈中弹出并存储到位置 2 的局部变量数组中。
3. 帧数据(FD):
它包含与该特定方法相关的所有符号引用(常量池解析)和正常方法返回。
它还包含对异常表的引用,该表在发生异常时提供相应的 catch 块信息。
如果您对此比较感兴趣,想了解更多相关知识,不妨来关注一下极悦的Java虚拟机视频,里面的课程内容丰富,通俗易懂,适合小白学习,希望对大家能够有所帮助哦。
你适合学Java吗?4大专业测评方法
代码逻辑 吸收能力 技术学习能力 综合素质
先测评确定适合在学习