📜  Java虚拟机(JVM)堆栈区域

📅  最后修改于: 2020-02-10 15:10:38             🧑  作者: Mango

对于每个线程,JVM创建线程时都会创建一个单独的堆栈。Java虚拟机堆栈的内存不必是连续的。Java虚拟机仅直接在Java堆栈上执行两项操作:推送和弹出框架。特定线程的堆栈可以称为运行时堆栈。该线程执行的每个方法调用都存储在相应的运行时堆栈中,包括参数、局部变量、中间计算和其他数据。完成方法后,将从堆栈中删除相应的条目。完成所有方法调用后,堆栈将变为空,在终止线程之前,JVM将销毁该堆栈。存储在堆栈中的数据可用于相应的线程,而不适用于其余线程。因此,我们可以说本地数据是线程安全的。堆栈中的每个条目都称为堆栈帧激活记录

 
堆栈框架结构
堆栈框架主要由部分组成:局部变量数组,操作数堆栈和框架数据。当JVM调用Java方法时,它首先检查类数据以确定该方法在局部变量数组中所需要的字数(局部变量数组和操作数堆栈的大小,对于每个单独的方法,以字为单位)。
操作数堆栈:它为调用的方法创建适当大小的堆栈框架,并将其压入Java堆栈。
 
1.局部变量数组(LVA):

  • 堆栈框架的局部变量部分为从零开始的单词数组。
  • 它包含该方法的所有参数和局部变量。
  • 数组array中的每个插槽或条目均为4字节。
  • int、float和reference类型的值在数组中占据1个条目或插槽,即4个字节。
  • double和long的值占据数组中的2个连续条目,即总共8个字节。
  • 在存储并占用1个时隙(即4个字节)之前,将Byte,short和char值转换为int类型
  • 但是,存储布尔值的方式因JVM而异。但是大多数JVM在本地变量数组中为布尔值提供了1个插槽。
  • 这些参数首先按照声明的顺序放入局部变量数组中。
  • 例如:让我们考虑一个具有方法bike()类的例子,然后局部变量数组如下图所示:
    // class声明
    class Example
    {
      public void bike(int i, long l, float f,
                   double d, Object o, byte b)
      {
      }
    }


    2.操作数堆栈(OS):

    • JVM使用操作数堆栈作为工作空间,就像粗糙的工作一样,或者可以说用于存储中间计算的结果。
    • 操作数堆栈被组织为单词数组,例如局部变量数组。但这不能通过使用像局部变量数组之类的索引来访问,而是通过一些可以将值压入操作数堆栈的指令,yi’j某些可以从操作数堆栈弹出值的指令以及一些可以执行所需操作的指令来访问。
    • 例如:这是JVM使用下面的代码的方式,该代码将减去包含两个int的两个局部变量并将int结果存储在第三个局部变量中:

     

    • 因此,这里的前两个指令iload_0iload_1将从本地变量数组将值推入操作数堆栈中。指令isub将减去这两个值,并将结果存储回操作数堆栈,在istore_2之后,结果将从操作数堆栈弹出并存储到位置2的局部变量数组中。

     
    3.帧数据(FD):

    • 它包含所有符号引用和与该特定方法有关的常规方法返回值。
    • 它还包含对异常表的引用,该表在发生异常的情况下提供了相应的捕获块信息。