语言处理器可大致分为解释器与编译器两种。这两类语言处理器的执行原理有很大差异。 解释器 解释器根据程序中的算法执行运算。简单来讲,它是一种用于执行程序的软件。如果执行的程序由虚拟机器语言或类似于机器语言的程序设计语言写成,这种软件也能称为虚拟机。 编译器 编译器能将某种语言写成的程序转换为另一种语言的程序。通常它会将原程序转换为机器语言程序。编译器转换程序的行为称为编译,转换前的程序称为源代码或源程序。如果编译器没有把源代码直接转换为机器语言,一般称为源代码转换器或源码转换器(source code translator)。 程序设计语言提供了何种类型的语言处理器不一而论,一些具有解释器,另一些则会提供编译器。例如,尽管C语言也提供了解释器,但却很少使用。C语言通常直接通过编译器转换为机器语言执行。转换后得到的机器语言程序会暂时保存至某个文件,需要借助操作系统来执行。 另一方面,Common Lisp或Haskell等语言一般会同时提供解释器与编译器,供用户根据需要选用。 有些语言混用解释器与编译器。通常,Java语言首先会通过编译器把源代码转换为Java二进制代码,并将这种虚拟的机器语言保存在文件中。之后,Java虚拟机的解释器将执行这段代码。 传统的狭义的编译器将会以文件形式保存转换后的程序。因此,只要源程序没有变更,编译就仅需执行一次,执行时间也会缩短。然而,一些编译器并不保存转换后的程序文件。这种编译器常见于解释器内部。 大多数Java虚拟机为了提高性能,会在执行过程中通过编译器将一部分Java二进制代码直接转换为机器语言使用。执行过程中进行的机器语言转换称为动态编译或JIT编译(Just-In-Time compile)。转换后得到的机器语言程序将被载入内存,由硬件执行,无需使用解释器。 编译器的用途多样。如上所述,它能够直接在解释器内部执行。此外,编译器的作用也不局限于将源程序转换为机器语言。例如,Ruby语言的解释器内部会通过编译器来执行预处理工作,将源程序转换为类似于Java二进制代码的虚拟机器语言程序。解释器真正执行的是这种经过编译的语言。这种设计提高了执行性能。 C 最近在解释器内部编译的例子越来越多,解释器的定义也变得模糊了呢。 F 是呀。不过前面提到的Java源代码将首先经过编译这一点,恐怕很多人并不知道吧。 H 的确如此,如果使用Eclipse开发Java程序,开发者很难看到编译过程。 F Eclipse其实已经把编译器与编辑器整合了,编译器会在开发者书写代码的同时执行编译,就好像编译始终能即时完成。 C 对,开发者要意识到代码已被编译反而是一件难事。 过去人们提到编译器时,首先会联想到费时的编译过程。不过由于编译后实际执行的是机器语言,因此执行速度很快。而对于解释器,人们通常认为它会在程序输入的同时立即执行,执行速度较慢。这就是两者的基本区别。现代的解释器内部常采用各种类型的编译器,已经越来越没有必要将解释器与编译器区分看待。 C 另外,编译器是否将源代码转换成了机器语言,并不那么易于分辨呢。 A 只要编译后的文件双击后能够运行,它就是机器语言了。 S 咦,但是Java编译后的.jar文件大都能双击运行不是吗? H 嗯,如果我说.jar文件的内部其实是机器语言,大概也会有人相信吧。 C 当然了,.jar文件内保存的是Java二进制代码。操作系统将会在后台启动Java虚拟机,并通过它来运行.jar文件。 F Android系统也是这种机制,它采用了名为Dalvik的虚拟机。