最近,花了四天的时间去看和虚拟机相关的资料,终于换来了一知半解。其实在N年前,我就碰到过虚拟机。那时候用的java、C#、vmware都和虚拟机有千丝万缕的关系。甚至,windows的保护模式也是虚拟机的一种。但是很多时候我不求甚解,对虚拟机的认识只停留在名词解析上面。也怪那时候的老师们从来不点破这层窗户纸,把Java教的和C一样,让我误以为Java就是C的移动版;把C#当做XX系统管理工具的专属语言来教。以至于我对那种技术的变化不是很在意。一直到遇到了Lua,我对虚拟机的认识有所不同了。虚拟机让Lua的编译结果实现了可以跨平台运行(Lua作者说ANSI C的功劳更大)。虚拟机分好几种,本文是讲述程序虚拟机。
那究竟什么是虚拟机呢?我们可以将虚拟机看作一个拥有特殊指令集的CPU,这种指令集可以存在于物理的计算机中,也可以是我们自己定义的一套指令集(比如Lua指令集、JVM指令集,CIL指令集等)。虚拟机去解析这些指令,然后将它们翻译物理计算机的指令,或者解析执行虚拟指令。
Lua是一种解析语言,但是它仍然存在编译过程(即词法分析、语义分析等过程)。Lua高级语言编译的结果得到字节码,Lua字节码就是我们上面说的虚拟指令,我们可以把字节码认为是一种机器语言,这种语言只有Lua虚拟机才认识(x86 CPU不认识)。然后通过翻译,把字节码变成和CPU相关的机器语言,或者一条条的去解析这种字节码的含义,然后去调用相应的功能。
Lua语言和Java以及C#没有本质的区别,它们的实现方式基本上一样。它们都是将一种高级语言,编译成一种虚拟指令(当然也可以直接编译成机器语言,编译成虚拟指令只是为了移植方便),然后去翻译、解析这种虚拟指令。这就决定了它们和编译语言C/C++之间运行速度的差别了(但差别不是很大,通常在一倍左右)。Lua自称为脚本语言,会让人觉得它很弱,我觉得脚本只是对语言用途的定位,它没有让自己成为java、c#那样大而全的语言,技术上没有什么区别。况且Java、C#都是基于栈的,而现今的Lua是基于寄存器的,让人觉得似乎Lua更加高级似得。
利用虚拟机实现语言的跨平台,似乎是Java首创,然后C#山寨跟进,后起的语言纷纷效仿。Lua语言除了基于寄存器的虚拟机是它的首创外,其他方面没有很大的创新。以至于我觉得那篇论文implementation of lua 5.0写的没有什么亮点(个人观点)。现在很多语言连自己的虚拟机都懒的写了,寄宿于Java的虚拟机,比如groovy。我觉得这是很好很经济的办法,站着他人的肩膀上实现自己的语言,而且Java的虚拟机可以为它们提供很好的资源和用户。
现在对虚拟机有一个新的认识了,下一站“栈”。谁知道栈啊?可以畅所欲言。我觉得语言的核心在于“栈”,但是技术的核心在于虚拟机。因为虚拟机是整个计算机的微缩版,而编译过程又是计算机理解高级语言的过程,也许“栈”就是内存吧。Lua虽小,五脏俱全。