虚拟机执行字节码的第一步就是把字节码读入内存。如果你刚刚读完用Golang实现四则运算 - 编译篇,那么你应该还能记得字节码文件的编码方式。虚拟机需要对字节码进行反序列化从而得到指令列表,整个过程就是序列化操作的逆操作。操作过程如下:

  1. 虚拟机首先检测MagicNumber是否正确,不正确则拒绝执行
  2. 读入4个字节并把其转化为整数,这个整数代表了接下来这个表达式的字节长度
  3. 根据表达式的长度读取相应的字节,这部分就是表达式的内容,之后保存到表达式列表中
  4. 重复步骤 2 ~ 4 直到所有的字节都读完

经过上面的步骤我们得到表达式的列表,之后我们对每一个表达式进行反序列化:

  1. 读取一个字节,这代表了这条指令的类型;若字节已经读取完毕则停止读取
  2. 如果是操作指令,保存指令到指令列表,跳转到步骤1
  3. 如果是数值指令,读取下一个字节获取数值类型(INT or FLOAT)
  4. 读取4个字节,根据数值类型把4个字节转化为数字
  5. 把数值指令和数字合并在一起创建为一条指令,把指令保存到指令列表
  6. 跳转到步骤1

通过上面的步骤我们得到了指令列表,之后我们开始执行指令,具体的执行过程参见源码,这里我们只是简单的了解一下虚拟机是如何执行指令的。

首先我们创建一个栈,根据指令的不同类型执行不同的操作:

  • 数值指令:将指令中的值压入栈
  • 操作指令:弹出栈顶的两个数值,对两个数执行相应指令的计算行为后将结果重新压入栈

指令执行完毕之后我们就能获取到表达式执行的最终结果了,打印结果,表达式运行结束。所有的表达式运行完毕,虚拟机退出。