解释器 vs 编译器 vs 虚拟机

36

我有一个关于解释器、编译器和虚拟机(VM)的问题。

现在我知道解释器和编译器之间的区别,但是虚拟机与前两者有什么不同呢?使用虚拟机相比于解释器和编译器有哪些优缺点呢?

非常感谢。

4个回答

39

一台虚拟机并不是编译器或解释器的替代品。我认为你在想JIT编译器,许多虚拟机都是这样实现的。

虚拟机本身就是其名称所描述的——一个不存在的机器(处理器)。例如,大多数处理器没有任何内在的方法来处理内存分配,也不具备任何类型知识。然而Java虚拟机(VM)却有一个new指令用于分配某个类的实例。VM的设计者决定将这个概念作为语言中重要的部分赋予其自己的操作码,这是VM中的基本操作单元。

创建自己的指令集的优点通常在于弥合了长时间编译/优化时间和慢速解释器之间的差距。例如,当你编译Java类时,你不需要进行寄存器分配、内联或任何传统编译器的工作。JIT会在以后执行该操作,但只针对您运行足够次数的代码部分,并分布在程序运行期间。JVM的指令集与Java非常接近,因此初始编译很快,并且对于VM来说阅读起来简单快捷,不像Java源代码那样。

至于解释器和JIT编译器的区别,通常是围绕运行时性能与开发时间之间的权衡。JIT需要更长的开发时间,但在运行时速度更快;然而,在许多情况下,例如脚本和中小型网站,程序运行时间太短,以至于你无法真正看到使用JIT带来的任何好处。

我还应该提到像VMware这样的软件。这也是一台虚拟机,但它使用的指令集也恰好用于真实的硬件上。它与语言VM具有相同的基本概念,即假装是一台不存在的物理机器,但在实践中却不同且非常复杂。


非常棒的伙计,正是我所需要的。 - DodoSombrero
5
“并不存在”并不是完全准确的表达。实际上,正确的说法应该是可能没有一种已制造的机器处理器可以消耗给定虚拟机的字节码语言。这并不意味着不能制造出这样的机器处理器。 - amirouche

25

通俗易懂版

编译器将一种语言转换为另一种语言。例如,将C#转换为IL、Java转换为字节码、C++转换为二进制机器代码。在编译阶段不进行执行。

解释器从源文件中逐行解释(执行)代码。例如PHP、Perl和其他脚本语言。

虚拟机可以指几个不同的东西,我知道其中两个:

  • 与Hypervisor相关的虚拟机,例如Hyper-VXen。它们允许您在单个硬件上运行多个操作系统
  • 软件运行时,如Java虚拟机公共语言运行时。这个软件允许您运行平台无关的中间语言(IL代码、字节码)并执行特定于机器的指令(即时编译)。通常,这样的虚拟机负责执行其他附属任务:资源管理、内存清理、线程、安全等

这三者没有优劣之分,它们执行不同的任务,很难进行比较。

语言和平台没有特定的顺序,还有数百个其他示例


编译器、解释器和虚拟机可以为任何语言编写,任何语言都可以被翻译成可由良好的虚拟机执行的形式。任何语言都可以被编译,当然也可以被解释。但这并不意味着这是一件有趣的事情。 - amirouche

6

实体机与虚拟机

  • 实体机的机器代码由硬件执行。
  • 虚拟机的“机器代码”是由解释器执行的。

解释器与编译器

答案在此处


3

虽然这是一个老问题,但我认为我可以增加价值。传统上,编译器或解释器将高级语言翻译成运行在目标计算机上的机器语言。

在虚拟机(VM)出现之前,每对高级语言和目标机器语言都需要一个独特的编译器或解释器。这导致了依赖于高级语言和目标计算机机器语言每个细节的编译器和解释器。

通过将高级语言到机器语言的翻译分为两个步骤并使用两个单独的程序,我们打破了这种依赖性。

第一个程序将高级语言翻译成中间代码。在Java中,这称为字节码。第一个程序仍然被称为编译器。

第二个程序将此中间代码翻译成目标计算机的机器语言。

运行中间代码的概念系统称为虚拟机。

现在同一编译器可以用于任何存在接受编译器生成的中间代码的虚拟机的计算机。

某些语言的编译器共享同一个VM,使得来自一个语言的例程可以轻松调用共享同一VM的另一种语言的例程。

关于VM的完整解释以及创建自己的VM的指导练习可以在Noam Nisan和Shimon Schoken的书《计算系统要素》中找到。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接