JVM学习笔记(九):基于栈的解释器执行过程

本文根据《深入理解java虚拟机》第8章部分内容整理

 

根据一个代码实例来介绍虚拟机中解释器的执行过程,代码如下所示:

 

Java代码 复制代码  收藏代码
  1. public int calculate(){   
  2.     int a = 100;   
  3.     int b = 200;   
  4.     int c = 300;   
  5.     return (a + b) * c;   
  6. }  
public int calculate(){
	int a = 100;
	int b = 200;
	int c = 300;
	return (a + b) * c;
}

由上面的代码可以看出,该方法的逻辑很简单,就是进行简单的四则运算加减乘除,我们编译代码后使用javap -verbose命令查看字节码指令,具体字节码代码如下所示: 

 

Dos代码 复制代码  收藏代码
  1. public int calculate();   
  2.   Code:   
  3.    Stack=2, Locals=4, Args_size=1  
  4.    0:   bipush  100  
  5.    2:   istore_1   
  6.    3:   sipush  200  
  7.    6:   istore_2   
  8.    7:   sipush  300  
  9.    10:  istore_3   
  10.    11:  iload_1   
  11.    12:  iload_2   
  12.    13:  iadd   
  13.    14:  iload_3   
  14.    15:  imul   
  15.    16:  ireturn   
  16.   LineNumberTable:   
  17.    line 30  
  18.    line 43  
  19.    line 57  
  20.    line 611  
  21.   
  22. }  
public int calculate();
  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
  LineNumberTable:
   line 3: 0
   line 4: 3
   line 5: 7
   line 6: 11

}

 根据字节码可以看出,这段代码需要深度为2的操作数栈(Stack=2)和4个Slot的局部变量空间(Locals=4)。下面,使用7张图片来描述上面的字节码代码执行过程中的代码、操作数栈和局部变量表的变化情况。

执行偏移地址为0的指令的情况

 

上图展示了执行偏移地址为0的指令的情况,bipush指令的作用是将单字节的整型常量值(-128~127)推入操作数栈顶,后跟一个参数,指明推送的常量值,这里是100。

执行偏移地址为1的指令的情况

 

上图则是执行偏移地址为1的指令,istore_1指令的作用是将操作数栈顶的整型值出栈并存放到第1个局部变量Slot中。后面四条指令(3、6、7、10)都是做同样的事情,也就是在对应代码中把变量a、b、c赋值为100、200、300。后面四条指令的图就不重复画了。

执行偏移地址为11的指令的情况

上面展示了执行偏移地址为11的指令,iload_1指令的作用是将局部变量第1个Slot中的整型值复制到操作数栈顶。

执行偏移地址为12的指令的情况

上图为执行偏移地址12的指令,iload_2指令的执行过程与iload_1类似,把第2个Slot的整型值入栈。

执行偏移地址为13的指令的情况

上图展示了执行偏移地址为13的指令情况,iadd指令的作用是将操作数栈中前两个栈顶元素出栈,做整型加法,然后把结果重新入栈。在iadd指令执行完毕后,栈中原有的100和200出栈,它们相加后的和300重新入栈。

执行偏移地址为14的指令的情况

上图为执行偏移地址为14的指令的情况,iload_3指令把存放在第3个局部变量Slot中的300入栈到操作数栈中。这时操作数栈为两个整数300,。

下一条偏移地址为15的指令imul是将操作数栈中前两个栈顶元素出栈,做整型乘法,然后把结果重新入栈,这里和iadd指令执行过程完全类似,所以就不重复画图了。

执行偏移地址为16的指令的情况

上图是最后一条指令也就是偏移地址为16的指令的执行过程,ireturn指令是方法返回指令之一,它将结束方法执行并将操作数栈顶的整型值返回给此方法的调用者。到此为止,该方法执行结束。

 

注:上面的执行过程只是一种概念模型,虚拟机最终会对执行过程做出一些优化来提高性能,实际的运作过程不一定完全符合概念模型的描述。不过从这段程序的执行过程也可以看出栈结构指令集的一般运行过程,整个运算过程的中间变量都是以操作数栈的出栈和入栈为信息交换途径。

你可能感兴趣的:(学习笔记)