JIT 机制浅谈
JIT 的定义
JIT 是 英文"Just In Time"的缩写,字面上的解释, 仿佛和程序没有太多关联。首先, 我们来给 JIT 下一个定义, 下面一段话非常贴切:
Whenever a program, while running, creates and runs some new executable code which was not part of the program when it was stored on disk, it’s a JIT.
历史上,术语JIT表达过哪些意义呢?幸运的是,卡尔加里大学的 John Aycock 写过一篇关于JIT技术历史的名为 "A Brief History of Just-In-Time"(可以 google 到这篇 PDF 文档)。根据 Aycock 的观点,历史上第一次明确提出在程序执行中生成代码并执行的概念的是麦卡锡(McCarthy's) 上世纪60 年代发表的关于 LISP 的论文。进一步, 汤姆森(Thompson's) 于1968 年关于正则表达式 的论文, 更加明确的提出正则表达式在执行时生成机器码。
詹姆斯高斯林(James Gosling)第一次在关于Java的技术文献中引入JIT,Aycock 认为 James Gosling 于 1990 年从制造领域中引入术语 JIT.
关于JIT的历史介绍点到此为止,如果你想了解更多的详细资料, 可以参考 Aycock 的文献。接下来, 我们将探讨上述定义在实际应用中的意义。
JIT 分成两个不同的阶段:
.阶段1: 在程序执行时生成机器码
.阶段2: 然后执行之
JIT 百分之99的工作在阶段1, 而这也是编译器所做的事情. 著名的编译器gcc 和 clang 转换 c/c++ 源码为机器码,机器码一般会输出到文件, 也有可能会在保持在内存中。 阶段2是本文要讨论的话题.
运行动态生成的机器码
现代操作系统对程序运行时的行为有严格的限制。随着CPU执行从早期的实模式演进到现在的保护模式,操作系统对虚拟内存段设置有不同的权限。在正常情况下,程序可以动态的从堆中申请内存并读写数据,但是不能运行在堆内存中的指令,除非向操作系统申请。
在这里需要指出,指令也是数数据。一个字节流,比如,
unsigned char[] code = {