java虚拟机栈空间

翻译自:https://www.geeksforgeeks.org/java-virtual-machine-jvm-stack-area/

在线程创建的时候,JVM会为每个线程创建一个单独的栈空间。JVM的栈内存不需要是连续的。JVM在栈上会进行两个操作:压入和弹出栈帧。对于一个特定的线程来说,栈被称为运行时栈(Run - Time Stack)。这个线程调用的每个方法会被存储在响应的运行时栈里,包括了参数,局部变量,计算媒介和其他数据。当一个方法运行结束的时候,相应的栈条目也会被移除掉。在一个线程的所有方法调用结束的时候,JVM会清空相应的栈内存,并在终止线程之前回收栈空间。在栈内存里的数据只可以被相对应的线程访问,其余的线程无法访问。所以我们可以说局部数据是线程安全的。每个栈的条目会被叫做栈帧(Stack Frame)或者活动记录(Activation Record)。
java虚拟机栈空间_第1张图片

栈帧结构

栈帧主要由部分组成:局部变量数组,操作数栈和栈数据区。当JVM调用一个Java方法的时候,首先它会检测类数据来决定字节数(局部变量数组和操作数栈的占用大小,每个独立的方法会进行一次单独的测算),会在局部变量数组和操作数栈中需要用到这个大小。随后JVM就会创建合适大小的栈帧用来作方法调用和入栈操作。

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

  • 栈帧的局部变量部分是由为索引0开始的字节数组构成。
  • 它包含了所有的方法参数和局部变量。
  • 在数组中的每个插槽或条目大小是4个字节。
  • int,float和引用类型在数组中全部占用一个条目或插槽,例如,4字节大小。
  • double和long类型的数据在数组中占用2个连续条目,例如,总共8字节大小。
  • byte,short和char类型在存储之前会被转化为int类型并且占用1个插槽,例如,4字节大小。
  • 但是存储boolean类型值的方式在不同的JVM中有不同的实现。在大多数JVM的实现中boolean类型在局部变量数组中占用一个插槽。
  • 参数会首先被放置如局部变量数组中,顺序是它们在方法中声明的顺序。
  • 例如: 一个类有一个方法叫做bike(),bike()方法的局部变量数组的存储情况如下图所示:
// Class Declaration
class Example
{
  public void bike(int i, long l, float f, 
               double d, Object o, byte b)
  {
     return 0;
  } 
}

java虚拟机栈空间_第2张图片

2. 操作数栈 Operand Stack (OS):

  • JVM使用操作数栈作为运行的工作空间或者我们也可以说用来存储计算的中间结果。
  • 操作数栈也像局部变量数组一样组织为一个数组。但是它不是使用索引来访问的而是由一些指令来访问,这些指令可以把值推进栈中,也可以把值从栈中弹出并且做一些我们需要的操作。
  • 例如:下面是一个例子,这个例子把两个int类型的局部变量进行相减,并且将结果int值存储在第三个局部变量中:
    java虚拟机栈空间_第3张图片
    这里的iload_0iload_1这两个指令会将值从局部变量数组中推入到操作数栈中。 isub指令会将这两个值相减然后把值存回到操作数栈中。然后在istore_2指令执行之后,结果值会从操作数栈中被弹出然后存入局部变量数组的第2个位置(索引为2)。
    java虚拟机栈空间_第4张图片

3. 栈帧数据区 Frame Data (FD):

  • 栈数据区包含了所有的符号引用(常量池解析)和普通方法的return位置,该return与特定的方法关联,用来跳转回去。
  • 它也包含了一个到异常表的引用,可以在异常发生的提供catch代码块的信息。

你可能感兴趣的:(java,jvm)