我一直知道解释器与编译器的区别. 编译器是事先将代码编译成机器码, 然后直接送进内存让 cpu 执行; 解释器则是解释执行代码, 可能会将代码先转换成一种中间码. 以前一直有一个误区就是解释器在解释执行的时候会把源代码或者中间码转成机器码, 也直接交由 cpu 执行, 然而我错了. 解释器是不会把源代码或者中间码转换成机器码的, 源代码或者中间码是直接在解释器内部的虚拟机上执行的.
当我认识到这一点之后, 我首先想到的虚拟机怎么实现的基本操作? 比如不借助 cpu 中的 ALU (加法器), 虚拟机怎么实现加法操作? 比如 2 + 3 这个表达式, 在词法分析后得到 "2" "+" "3" 三个 token, 虚拟机可以知道这是加法, 但是它怎么知道 "2" 和 "3" 分别代表多少? 2 + 3 它要怎么计算? 这是虚拟机无法模拟的. 略加思考, 我明白了, 试想一下, 虚拟机是什么语言写的? 虚拟机又是运行在哪里?
对的, 虚拟机本质上还是一坨直接运行于 cpu 之上的机器码, 当它拿到 "2" "+" "3" 的时候, 就直接讲这道题交给 cpu 的 ALU 去完成了, 然后取得结果作为它所解释的程序的运行结果.
那么 JIT (Just in Time) 是什么呢? JIT 实际上还是将源代码编译成机器码交由 cpu 执行. 可是从上述过程中可以看到, 虚拟机自己已经能够解释执行源程序了, 为什么还要将源代码编译成机器码交给 cpu 执行呢? 这是因为虚拟机毕竟也是跑在 cpu 上的程序, 一段相同的逻辑由虚拟机解释执行毕竟没有直接交给 cpu 执行更快.
但是编译也是耗时的啊, 开 JIT 虽然能把源代码编译成机器码, 但是一遍解释一遍编译, 那不会将机器码执行快速的优势抵消吗? 这就是一个权衡的问题了, 程序设计中有一个定律叫做 90% 的工作实际上是由 10% 的代码完成的. 所以 JIT 尽可能做到的就是找出这 10% 的代码仅将它们给编译了, 这样就 ok 了.
Thank you @cifer