java - Pushing variables to Stack 和 Variables living in the Stack 的区别?

标签 java memory-management jvm stack bytecode

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

我还知道,如果您创建一个局部变量,它将存在于堆栈中,而不是堆中。随着我们将数据插入堆栈,堆栈将增长,如下所示:

enter image description here

现在我会试着把我遇到的困惑转嫁给你:

例如这个简单的 Java 代码:

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

被翻译成这个字节码:

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;

根据定义 acons_null 是:

push a null reference onto the stack

astore_1 是:

store a reference into local variable 1

我感到困惑的是,我们将 foo 压入堆栈,然后又将其存储在堆栈中?在局部变量中存储引用是什么意思?那个局部变量在哪里?我们将 foo 插入的堆栈还是这些单独的堆栈?

此时,如果我在第一个压入堆栈的对象上调用一个方法,由于堆栈指针指向我压入的最后一个元素,它将如何处理?

最佳答案

在 JVM 中,每个线程都存在一个堆栈。每个堆栈由多个组成:每个方法调用都会创建一个新帧,当方法调用完成时,该帧将被销毁。

在栈帧中有两个区域:

  1. 操作数堆栈(不要将此处的“堆栈”一词与 JVM 堆栈本身混淆——此处的堆栈表示该区域为后进先出结构)。<
  2. 一组局部变量,其中每个变量都有一个索引(从零开始)。

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

description of aconst_null 中所述, aconst_null指令推送 null对象引用到操作数栈

description of astore_<n> 中所述(其中 n 可以是 0、1、2 或 3):

The <n> must be an index into the local variable array of the current frame (§2.6). The objectref on the top of the operand stack must be of type returnAddress or of type reference. It is popped from the operand stack, and the value of the local variable at <n> is set to objectref.

因此在您的示例中,语句 Object foo = null翻译成以下内容:

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

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

来源:Java 虚拟机规范(参见 this section)。

关于java - Pushing variables to Stack 和 Variables living in the Stack 的区别?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29946187/

相关文章:

java - 打开另一个 JDialog 时,模态 JDialog 被推到后面

java - 如何像在 Cocos2d 中那样在 Libgdx 中将子图像添加到 Sprite 中?

java - 将图像添加到 Android Studio 1.3.1 项目

java - 如何消除 JVM 运行时错误弹出窗口?

java - 为什么 JVM 不将 "incrementing a int variable"编译为原子获取和递增操作?

java - 遇到数组问题(涉及用户多个输入)?

windows - CreateFileMapping,MapViewOfFile,如何避免占用系统内存

c - 重新分配数组 (C99)

python - 我可以在 Keras 中分步训练模型吗?

java - 如何设置Jenkins使用系统的日期,时间,数字和货币格式?