• Tags
  •         
  • www.breakyizhan.com
  •    

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

    堆栈帧结构

    堆栈帧基本由部分组成:局部变量数组,操作数堆栈和帧数据。当JVM调用Java方法时,首先检查类数据,以确定本地变量数组中方法所需的单词数量(本地变量数组和单个操作数堆栈的大小)操作数堆栈。它为调用的方法创建适当大小的堆栈框架并将其推送到Java堆栈。

    1.局部变量数组(LVA):

    • 堆栈帧的局部变量部分被组织为基于零的单词阵列。
    • 它包含该方法的所有参数和局部变量。
    • 阵列中的每个插槽或条目都是4个字节。
    • int,float和reference类型的值在数组中占用1个入口或插槽,即4个字节。
    • double和long的值占用阵列中的2个连续条目,即总共8个字节。
    • 字节,short和char值将在存储并占用1个时隙(即4个字节)之前转换为int类型
    • 但是,存储布尔值的方式从jvm到jvm不等。但是大多数jvm在本地变量数组中为布尔值提供了1个槽。
    • 参数首先按照
      声明的顺序放置在局部变量数组中。
    • 例如:让我们考虑一个具有方法bike()的类示例,然后局部变量数组将如下图所示:
    // Class Declaration
    class Example
    {
      public void bike(int i, long l, float f, 
                   double d, Object o, byte b)
      {
         return 0;
      } 
    }

    2.操作数堆栈(OS):

    • JVM使用操作数堆栈作为粗略工作的工作空间,或者我们可以说存储中间计算的结果。
    • 操作数堆栈被组织为像本地变量数组这样的单词数组。但是这不是通过使用像局部变量数组这样的索引来访问的,而是通过一些可以将值推送到操作数堆栈的指令来访问的,以及一些可以从操作数堆栈中弹出值的指令以及一些可以执行所需操作的指令的指令。
    • 例如:下面是JVM如何使用下面的代码,它将减去两个包含两个int的局部变量,并将int结果存储在第三个局部变量中:

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

    3.帧数据(FD):

    • 它包含与该特定方法相关的所有符号引用(常量池分辨率)和常规方法返回值。
    • 它还包含对异常表的引用,异常表在异常情况下提供相应的catch块信息。

     
    转载请保留页面地址:https://www.breakyizhan.com/java/3705.html