Java核心技术之虚拟机字节码执行引擎---基于栈的字节码解释执行引擎

 Java虚拟机的执行引擎在执行Java代码的时候都有解释执行(通过解释器执行)编译执行(通过即时编译器产生本地代码执行) 两种选择。

解释执行

 Java语言经常被人们定位为“解释执行”的语言,但主流的虚拟机中都包含了即时编译器后,Class文件中的代码到底会被解释执行还是编译执行,就成了只有虚拟机自己才能准确判断的事情。

编译过程
在这里插入图片描述
 Java语言中,Javac编译器完成了程序代码经过词法分析、语法分析到抽象语法树,再遍历语法树生成线性的字节码指令流的过程。因为这一部分动作是在Java虚拟机之外进行的,而解释器在虚拟机的内部,所以Java程序的编译就是半独立的实现

基于栈的指令集与基于寄存器的指令集

 Java编译器输出的指令流,基本上是一种基于栈的指令集架构(Instruction SetArchitecture,ISA),指令流中的指令大部分都是零地址指令,它们依赖操作数栈进行工作
 与之相对的另外一套常用的指令集架构是基于寄存器的指令集,最典型的就是x86的二地址指令集,说得通俗一些,就是现在我们主流PC机中直接支持的指令集架构,这些指令依赖寄存器进行工作

使用基于栈的指令集计算“1+1”

iconst_1
iconst_1
iadd
istore_0

 两条iconst_1指令连续把两个常量1压入栈后,iadd指令把栈顶的两个值出栈、相加,然后把结果放回栈顶,最后istore_0把栈顶的值放到局部变量表的第0个Slot中。

使用基于寄存器的指令集计算“1+1”

mov eax,1
add eax,1

 mov指令把EAX寄存器的值设为1,然后add指令再把这个值加1,结果就保存在EAX寄存器里面。

基于栈的指令集主要的优点就是可移植,寄存器由硬件直接提供,程序直接依赖这些硬件寄存器则不可避免地要受到硬件的约束。栈架构指令集的主要缺点是执行速度相对来说会稍慢一些。所有主流物理机的指令集都是寄存器架构也从侧面印证了这一点。

基于栈的解释器执行过程

一段简单的算术代码

public int calc(){
	int a=100int b=200int c=300return(a+b)*c;
}

使用javap命令查看字节码指令

public int calc();
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
}

 javap提示这段代码需要深度为2的操作数栈和4个Slot的局部变量空间。

执行偏移地址为0的指令的情况
在这里插入图片描述
执行偏移地址为1的指令的情况
在这里插入图片描述
执行偏移地址为11的指令的情况
在这里插入图片描述
执行偏移地址为12的指令的情况
在这里插入图片描述
执行偏移地址为13的指令的情况
在这里插入图片描述
执行偏移地址为14的指令的情况
在这里插入图片描述
执行偏移地址为16的指令的情况
在这里插入图片描述
 上面的执行过程仅仅是一种概念模型,虚拟机最终会对执行过程做一些优化来提高性能,实际的运作过程不一定完全符合概念模型的描述……更准确地说,实际情况会和上面描述的概念模型差距非常大,这种差距产生的原因是虚拟机中解析器和即时编译器都会对输入的字节码进行优化。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值