虚拟机字节码执行引擎_02
基于栈的字节码解释执行引擎
这个栈,就是栈帧中的操作数栈。
解释执行
先通过 javac 将代码编译成字节码,虚拟机再通过加载字节码文件,解释执行字节码文件生成机器码,解释执行的流程如下:
1 |
词法分析 -> 语法分析 -> 形成抽象语法树 -> 遍历语法树生成线性字节码指令流 |
指令集分类
基于栈的指令集
优点:
- 可移植:寄存器由硬件直接提供,程序如果直接依赖这些硬件寄存器,会不可避免的受到硬件的约束;
- 代码更紧凑:字节码中每个字节对应一条指令,多地址指令集中还需要存放参数;
- 编译器实现更简单:不需要考虑空间分配问题,所需的空间都在栈上操作。
缺点: 执行速度稍慢
- 完成相同的功能,需要更多的指令,因为出入栈本身就产生相当多的指令;
- 频繁的栈访问导致频繁的内存访问,对于处理器而言,内存是执行速度的瓶颈。
示例: 两数相加
1 2 3 4iconst_1 // 把常量1入栈 iconst_1 iadd // 把栈顶两元素出栈相加,结果入栈 istore_0 // 把栈顶值存入第0个Slot中
基于寄存器的指令集
示例: 两数相加
1 2 |
mov eax, 1 add eax, 1 |
执行过程分析
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 |
public class Architecture { /* calc函数的字节码分析: public int calc(); descriptor: ()I flags: ACC_PUBLIC Code: stack=2, locals=4, args_size=1 // stack=2,说明需要深度为2的操作数栈 // locals=4,说明需要4个Slot的局部变量表 0: bipush 100 // 将单字节的整型常数值push到操作数栈 2: istore_1 // 将操作数栈顶的整型值出栈并存放到第一个局部变量Slot中 3: sipush 200 6: istore_2 7: sipush 300 10: istore_3 11: iload_1 // 将局部变量表第一个Slot中的整型值复制到操作数栈顶 12: iload_2 13: iadd // 将操作数栈中头两个元素出栈并相加,将结果重新入栈 14: iload_3 15: imul // 将操作数栈中头两个元素出栈并相乘,将结果重新入栈 16: ireturn // 返回指令,结束方法执行,将操作数栈顶的整型值返回给此方法的调用者 */ public int calc() { int a = 100; int b = 200; int c = 300; return (a + b) * c; } public static void main(String[] args) { Architecture architecture = new Architecture(); architecture.calc(); } } |
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来源 xhj的博客!