How Stack And Heap Work

    713
    最后修改于

    已知 JVM 线程运行时候,存在线程之间共享的堆内存,以及线程独有的线程栈。
    其中堆区主要用来存储一些运行时数据,如启动时加载的类,创建的各种对象。而栈区则主要用来存储线程栈,每个线程栈中又是由函数栈帧组成,每个函数调用对应一个栈帧,其中包括:局部变量表,操作数栈等。
    loading...

    从例子入手#

    java
    public class Tmp {  
        public int a = 42;  
    	public static void main(String[] args) {  
            Tmp tmp = new Tmp();  
            int x = tmp.a;  
            tmp.a = x + 1;
        }
    }
    

    如果不考虑 main 函数,这个类在用javac编译后大概是这样

    java
    public class Tmp {  
        public <init>()V  
    	L0    LINENUMBER 1 L0  
        ALOAD 0  
        INVOKESPECIAL java/lang/Object.<init> ()V  
    	L1    LINENUMBER 2 L1  
        ALOAD 0  
        BIPUSH 42  
        PUTFIELD Tmp.a : I  
    	RETURN    MAXSTACK = 2  
        MAXLOCALS = 1  
    }
    

    而我们要执行的main方法则是这样的

    java
        public static main([Ljava/lang/String;)V  
    	// line 0 Tmp tmp = new Tmp();
        NEW Tmp
    	DUP
    	INVOKESPECIAL Tmp.<init> ()V
    	ASTORE 1
    	// line 1  int x = tmp.a;  
        ALOAD 1  
        GETFIELD Tmp.a : I  
        ISTORE 2  
    	// line 2  tmp.a = x + 1; 
        ALOAD 1
        ILOAD 2
        ICONST_1  
    	IADD
    	PUTFIELD Tmp.a : I
    	// line 3 return line  
    	RETURN    MAXSTACK = 3  
        MAXLOCALS = 3 
    

    loading...

    当执行第 0 行Tmp tmp = new Tmp();的时候,会进行如下操作:

    1. NEW Tmp,在堆中申请一块 Tmp 对象的内存,并将其引用压入操作数栈。
    2. DUP 复制操作数栈栈顶的元素(也就是 Tmp 的引用)
    3. INVOKESPECIAL Tmp.<init> ()V 执行 Tmp 的初始化函数。
    4. ASTORE 1 将操作数栈顶的元素出栈放入操作数栈
      loading...
      紧接着第 1 行int x = tmp.a;
    5. ALOAD 1 将局部变量表中的 #1 放入操作数栈。
    6. GETFIELD Tmp.a : I 弹出操作数栈顶的引用,将其作为 Tmp 从堆中取字段 a 的值(Int 类型)放入栈顶
    7. ISTORE 2 弹出操作数栈顶,将其存入局部变量表 #2
      loading...
      随后第 2 行tmp.a = x + 1;
    8. ALOAD 1 将局部变量表中的 #1 放入操作数栈。
    9. ILOAD 2 将局部变量表中的 #2 放入操作数栈。
    10. ICONST_1 将 Int 常量放入操作数栈。
    11. IADD 弹出栈顶两个元素,将其相加,结果放入操作数栈。
    12. PUTFIELD Tmp.a : I 弹出栈顶元素 (上一条指令结果),弹出栈顶(tmp 引用),将其放入内存中 tmp.a 字段中。
      loading...
      最后则是main 方法的返回语句,直接跳过。

    从上面的例子不难看出,JVM 是基于 Stack 的 Virtual Machine。与在 Architecture 中介绍的寄存器式 CPU 有很大不同。

    • 🥳0
    • 👍0
    • 💩0
    • 🤩0