Jvm笔记总结(十一):基于栈的字节码解释执行引擎
PS : 本文乃学习整理参考而来 ,目录参考 [ Jvm系列目录 ]
解释执行:Java语言经常被人们定位为“解释执行”的语言,在Java初生的JDK1.0时代,这种定义是比较准确的。但当前主流的虚拟机中都包含了即时编译后,Class文件中的代码到底是能被解释执行还是编译执行,只有虚拟机自己才能判断。这时候再笼统的说“解释执行”,对整个Java来说就是没有意义的概念。只有确定了Java实现版本以及虚拟机版本,再谈论Java属于解释执行还是编译执行才会更准确。
基于栈的指令集与基于寄存器的指令集:
Java编译器输出的指令流,是一种基于栈的指令集架构,指令流中的指令大部分是零地址指令(方法表Code中的指令),他们依赖操作数栈进行工作。与之相对的是一套常用的指令集架构是基于寄存器的指令集,他依赖寄存器进行工作。
如下分别使用两种指令集计算“1+1”的结果,
基于栈的指令集:
iconst_1
iconst_1
iadd
istore_0
两条iconst_1指令连续把两个常量1压入操作栈后,iadd指令把栈顶的两个值出栈、相加,然后把结果放回栈顶,最后istore_0把栈顶值放到局部变量表的第0个Slot中。
基于寄存器:
mov eax,1
add eax,1
mov指令把EAX寄存器的值设为1,然后add指令再把值加1,结果就保存在EAX寄存器里面。
栈指令集的优点与寄存器指令集的缺点:
基于栈的指令集主要的优点就是可移植性,不会受硬件的不同而受影响。而基于寄存器的指令集,程序直接依赖这些硬件寄存器,不同的硬件设备,则不可避免受到约束。而使用栈架构的指令集,用户程序不会直接使用这些寄存器,而是由虚拟机来完成与寄存器的交互,从而避免直接与硬件交互。
栈指令集的缺点与寄存器指令集的优点:
基于栈指令集的主要缺点是执行速度相对来说会稍慢一些。而相对的基于寄存器指令集的执行速度会相对较优。
基于栈的解释器执行过程
通过如下代码解释基于栈的解释器执行过程:
public int calc() {
int a = 100;
int b = 200;
int c = 300;
return (a + b) * c;
}
使用javap命令后得如下反编译代码:
public int calc();
descriptor: ()I
flags: ACC_PUBLIC
Code:
stack=2, locals=4, args_size=1
0: bipush 100
2: istore_1
3: sipush 200
6: istore_2
7: sipush 300
10: istore_3
11: iload_1
12: iload_2
13: iadd
14: iload_3
15: imul
16: ireturn
如下7图对该过程进行描述