编译器与解释器

世界上主要存在两种类型的编程语言——一种依靠解释器直接运行,被称为解释型语言,另一种先将代码编译到目标平台的二进制码,然后运行这些二进制代码,被称为编译型语言

前者很简洁,免去了编译的困扰,打开就开始一行一行地运行代码,并且具有更好的自由度,可以在运行代码时更灵活地做出改变。比如 Python 就属于这种类型的编程语言。

而后者虽然多了编译这一步骤,但编译后的代码执行速度很快。只要源代码不更改,一次编译便可以永远享受编译后代码的高速。并且,由于编译器是整个读入代码,再输出为二进制码,相比于一行行运行程序地解释器,知道程序的整体结构是什么样子,因此也能对程序进行性能方面的优化。当然,相比于前者,由于引入了编译与优化的步骤,程序的灵活性必然会受到一定的影响,这也是编译型语言为了性能所必须做出的一些取舍。比如 C/C++就属于这种类型的编程语言。

然而,事实上情况并非总是这么简单。例如 Java 实际上是先将源代码(.java 文件)编译为 Java 字节码(.class)文件,然后通过一个被称为”Java 虚拟机“的环境解释运行字节码的。这样做能使 Java 代码在各种不同的平台上运行而无需考虑兼容性问题——只需要对应平台安装了对应平台版本的 Java 虚拟机。因此,人们说 Java 是一门”跨平台“的编程语言。而相比于努力让编译后的代码直接在各种平台上运行,只保证 Java 虚拟机在各种平台上能够正常运行则要简单的多,并且不容易发生意外。

此外,通过使用虚拟机运行代码,还能较为轻松地实现”垃圾回收“功能,即能够让程序自动以尽可能高效地方式管理内存的分配与回收,而无需程序员手动释放内存——例如 C/C++就是需要程序员手动释放内存、不包含垃圾回收器的语言,这为编码造成了许多麻烦。

这样使用虚拟机的语言还有很多,并且占据主流。Python、Ruby、JavaScript、Java、C#等都是具有虚拟机与垃圾回收器的编程语言。

可以看到,其实 Python 也不完全是一门解释型语言——Python 事实上在运行一段程序之前也会将其编译为 Python 字节码(bytecode),然后通过解释器逐行运行字节码。只是这个过程要简单得多,不像 Java/C++等编程语言会在编译期间做大量的检查及优化工作,因此一般仍旧认为 Python 是一门解释型语言。并且通常来说,我们也将 Java 这样的编程语言认为是一门编译型语言。

不过,虚拟机当然是存在代价的,而这一代价就是性能。通过虚拟机运行程序,毕竟不是直接通过原生代码运行程序,性能上必然会有损失。Java 虚拟机通过数十年的努力在通常情况下达到了接近 C++编译成的原生代码的性能,但在许多情况下,很多场景仍旧因为需要极高的性能而只能选择 C++而不是 Java。并且,Java 虚拟机高性能的一个代价就是需要占用大量的内存,这也体现在另一个同样规模庞大的前端 JavaScript 引擎 V8 上——你或许可以感受到,Chrome 浏览器在标签页开多了之后会有比较明显的卡顿,这和 V8 引擎较大的内存占用不无关系。

Last updated