将局部变量存在栈帧中,在通过 rbp 寄存器加 局部变量相对于rbp的地址偏移值(编译期确定) 来定位到具体参数。
JAVA 栈帧 编译前 编译后-
aload_0:将局部变量表中第一个局部变量的引用推到栈顶。在Java虚拟机中对于非静态方法调用,会将当前对象引用放入到局部变量表中第一个局部变量位置。【调用方法指令前,需要将调用方法的对象加入到操作数栈中。此步骤是调用构造函数的一个中间步骤】
-
astroe_0:将栈顶引用类型值保存到局部变量0中。
-
getfield:getfield指令用来获取栈顶元素(2步骤入栈元素)的指定成员变量,在此会将栈顶元素(2步骤入栈元素)出栈,并将获取成员变量入栈。
-
invokevirtual: i如果调用的方法描述中需要传入参数,则会将当前操作数栈顶元素作为方法的参数,并从操作数中出栈。当参数出栈完毕或方法不需要传入参数,会将当前栈顶元素作为方法调用的对象,并从操作数栈中出栈。
Java中的栈帧有点像C语言中的栈帧+寄存器组。其中:
- 局部变量表 + 动态链接 + 方法返回相当于C语言中的栈帧。
- 操作数栈相当于C语言中的寄存器组。
因为C语言编译成的汇编语言的指令集基本都是针对寄存器来进行操作的,而Java语言编译成的指令集 则是通过操作数栈来进行实现的。这样的设计使得Java在这一块可以屏蔽掉底层硬件的不同的寄存器组的个数等的差异。
JVM 源码分析 猜测JAVA 在JIT编译时将操作数栈的相关内容直接编译为寄存器组使用,操作数过长时使用内存。
对应JVM源码//TODO



