将变量推送到堆栈中的Stack和Variables差异?

Kor*_*gay 13 java stack jvm memory-management bytecode

所以我知道存在2个内存区域:StackHeap.

我也知道如果你创建一个局部变量,它将存在于堆栈中,而不是堆中.随着我们将数据推入其中,堆栈将会增长,如:

在此输入图像描述

现在我将尝试通过我对你的困惑:

例如,这个简单的Java代码:

public class TestClass {
    public static void main(String[] args)  {
        Object foo = null;
        Object bar = null;
    }
}
Run Code Online (Sandbox Code Playgroud)

被翻译成这个字节码:

public static void main(java.lang.String[]);
  Code:
   Stack=1, Locals=3, Args_size=1
   0:   aconst_null
   1:   astore_1
   2:   aconst_null
   3:   astore_2
   4:   return

LineNumberTable: 
line 5: 0
line 6: 2
line 7: 4

LocalVariableTable: 
Start  Length  Slot  Name   Signature
0      5      0    args       [Ljava/lang/String;
2      3      1    foo       Ljava/lang/Object;
4      1      2    bar       Ljava/lang/Object;
Run Code Online (Sandbox Code Playgroud)

根据定义,acons_null是:

push a null reference onto the stack
Run Code Online (Sandbox Code Playgroud)

astore_1是:

store a reference into local variable 1
Run Code Online (Sandbox Code Playgroud)

我遇到的困惑是,我们将foo推入堆栈,然后我们将它再次存储在堆栈中?将引用存储在局部变量中意味着什么?该局部变量在哪里生活?同样的堆栈我们将foo推入或者是这些单独的堆栈?

现在,如果我在第一个对象上调用一个方法,我将其推入堆栈,因为堆栈指针指向我推送的最后一个元素,它将如何处理?

man*_*uti 13

JVM中每个线程都有一个堆栈.每个堆栈由几个框架组成:每个方法调用都会创建一个新框架,并且在完成方法调用时,框架将被销毁.

在堆栈框架内有两个区域:

  1. 操作数栈(不要混淆单词"堆"在这里与JVM栈本身-堆在这里表示的区域作为一个后进先出的结构).
  2. 一组局部变量,其中每个变量都有一个索引(从零开始).

根据JVM实现,它们在内存中可能是连续的,也可能不是连续的.从逻辑上讲,它们是堆栈框架的两个独立部分.

如在描述中aconst_null所解释,该aconst_null指令将null对象引用推送到操作数堆栈上.

并且如在(其中可能是0,1,2或3)的描述中astore_<n>所解释的n:

<n>必须是一个指数到当前帧(§2.6)的本地变量数组.在objectref操作数堆栈的顶部的类型必须是returnAddress或类型的reference.它从操作数堆栈中弹出,并将局部变量at的<n>值设置为objectref.

因此,在您的示例中,该语句Object foo = null转换为以下内容:

  1. null(指向"无"的特殊引用)推到操作数堆栈的顶部.
  operand stack
   __________
  |   null   | <-- null is pushed on the operand stack
  |__________|
  |          |
  |__________|
  |          |
  |__________|
Run Code Online (Sandbox Code Playgroud)
  1. 从操作数堆栈弹出引用并将其存储在索引1的局部变量中.此局部变量对应于foo.
  operand stack                           local variables
   __________      _______________ _______________ _______________ _______________
  |          |    |      args     |   foo (null)  |               |               |
  |__________|    |_______0_______|_______1_______|_______2_______|_______3_______|
  |          |                    store null in LV#1 
  |__________|
  |          |
  |__________|
Run Code Online (Sandbox Code Playgroud)

Object bar = null除了null存储在索引2的局部变量中之外,执行相同的步骤.

来源:Java虚拟机规范(参见本节).