解决方法
这台机器镜像物理机器,至少在合理和有用的范围内.它经常有一个用于指令的存储器,一个程序计数器,一个用于存储中间值和返回地址的堆栈等.一些更复杂的机器也有寄存器.有一个固定且相对原始的(与Ruby之类的语言相比,不与实际的cpu指令集相比)指令集.像cpu一样,虚拟机无休止地循环:
>读取当前指令(由程序计数器识别).
>(解码它,虽然这通常比真实的cpu简单得多,至少比CISC简单.)
>执行它(在过程中可操作堆栈和/或寄存器).
>更新程序计数器.
使用解释器,所有这些都通过间接层发生.你的实际物理cpu不知道它在做什么. VM本身就是软件,上面的每个步骤都是委托给cpu的几个(在具有相当高级字节码指令的情况下,可能是几十或几百个)物理cpu周期.每次读取指令时都会发生这种情况.
输入JIT编译.最简单的形式只是将每个字节码指令替换为在解释器遇到它时将执行的代码(稍微优化)的副本.这已经使速度获胜,例如程序计数器操作可以省略.但是甚至还有更聪明的变种.
例如,跟踪JIT以常规解释器开始,并另外观察它们执行的程序.如果他们注意到程序在特定代码段中花费了大量时间(几乎总是,循环或从循环中调用的函数),它会开始记录它在此期间的作用 – 它会生成一个跟踪.当它到达开始记录的点(循环的一次迭代之后)时,它会调用它一天并将跟踪编译为机器代码.但是由于它看到了程序在运行时的实际行为,它可以生成完全符合此行为的代码.以循环添加整数为例.机器代码不包含解释器实际执行的任何类型检查和函数调用.至少,它不会包含大部分内容.为了确保正确性,将添加检查记录跟踪的条件(例如所涉及的变量是整数)仍然成立.当这样的检查失败时,它会退出并重新开始解释,直到记录另一条跟踪.但在此之前,它可以以与手写C代码相媲美的速度执行一百次迭代.