因此,例如,Python和Java有VM,C和Haskell没有。 (如果我错了,请纠正我)
考虑到线路两侧有哪些语言,我找不到原因。 Java在很多方面都是静态的,而Haskell提供了许多动态特性。
答案 0 :(得分:27)
这与静态与动态无关。
相反,它是关于独立于底层硬件平台(“构建一次,随处运行” - 理论上......)
实际上,它与语言无关。可以编写一个为JVM生成字节码的C编译器。可以编写一个生成x86机器代码的Java编译器。
答案 1 :(得分:18)
让我们忘记VM一秒钟(我保证会回到下面的那些,我保证),并从这个重要的事实开始:
对于提供垃圾收集的语言,必须有某种“runtime” / runtime-environment / thing来执行它。
这就是为什么Python,Java和Haskell需要“运行时”,而C则不能直接编译为本机代码。
请注意psyco是一个Python优化器,它将Python代码编译为机器代码,但是,很多机器代码都包含对C-Python运行时函数的调用,例如PyImport_AddModule
,{{ 1}}等等。
Haskell / GHC与psyco编译的Python类似。 PyImport_GetModuleDict
被添加为简单的机器指令,但更复杂的东西分配对象等,调用运行时。
还有什么?
如果我们要向C添加例外,我们生成的机器代码需要为每个函数和每个函数调用做一些事情。
如果我们再添加“闭包”,则会添加更多内容。
现在,我们不是在每个函数中重复使用此样板机器代码,而是调用子程序来执行必要的操作,例如PyErr_Occurred
。
现在,基本上每个原始源代码行映射到某些函数的调用和较小的唯一部分。
这是一个想法(顺便说一下,我们称这个想法为“虚拟机”)。
让我们代表您的Python代码,例如:
Int
作为内存数据结构,例如:
def has_no_letters(text):
return text.upper() == text.lower()
现在,让我们编写一个执行此内存数据结构的解释器。
让我们讨论一下这对直接来自文本解释器的好处,然后讨论编译到机器代码的好处。
{ 'func_name': 'has_no_letters',
'num_args': 1,
'kwargs': [],
'codez': [
('get_attr', 'tmp_a', 'arg_0', 'upper'), # tmp_a = arg_0.upper
('func_call', 'tmp_b', 'tmp_a', []), # tmp_b = tmp_a() # tmp_b = arg_0.upper()
('get_attr', 'tmp_c', 'arg_0', 'lower'),
('func_call', 'tmp_d', 'tmp_c', []),
('get_global', 'tmp_e', '=='),
('func_call', 'tmp_f', 'tmp_e', ['tmp_b', 'tmp_d']),
('return', 'tmp_f'),
]
}
答案 2 :(得分:4)
VM(虚拟机)实际上是语言设计者的工具,可以避免在编写语言实现时出现一些复杂性。
基本上是虚拟计算机的规范以及每台计算机如何与另一台计算机进行交互。您可以在本规范中编写一些可以由实际语言使用的假设。
在本规范中,通常您可以定义处理器/处理器的工作方式,内存的工作方式,可能的读/写屏障等,以及与之交互的简单汇编语言。
最终语言通常从您正在编写的文本文件中翻译(编译)为为该机器编写的表示。
这有一些优点:
还有一个很酷的因素:Look Ma我做了一个虚拟机:)。
答案 3 :(得分:3)
来自Virtual Machines上的维基百科条目:
“虚拟机(VM)是执行类似物理机器的程序的机器(即计算机)的软件实现。”
理论上,虚拟机的最大资产是代码可移植性 - “一次编写,随处运行”
可能最着名的虚拟机示例是JVM,最初设计用于运行Java代码,但现在也越来越多地用于语言,如Clojure和Scala。
动态语言并不特定,这意味着他们需要VM。但是,他们需要interpreter,可以在虚拟机上构建。
答案 4 :(得分:3)
虚拟机基本上是一个解释器,可以解释更接近机器代码的语言。当真机解释真实的机器代码时,虚拟机会解释一个虚构的机器代码。有些VM解释了实际计算机的机器代码 - 这些被称为模拟器。
为简单的汇编语言编写解释器更容易,然后为完整的高级语言编写解释器。此外,许多高级代码构造通常只是一些基本原则的语法糖。因此,编写一个将所有复杂概念转换为简单VM语言的编译器会更容易,因此我们不必编写复杂的解释器,而是可以使用简单的解释器(VM)。然后您有更多时间来优化VM。
这基本上是如何实现当今大多数语言(不编译成真实的机器代码)。
解释器(VM)和编译器可以是单独的程序(如java
和javac
),也可以只是一个程序(如Ruby或Python)。
答案 5 :(得分:2)
没有“需要”,任何这些语言都提供直接发出机器代码的编译器,以在给定的体系结构中实现其语言的语义。
虚拟机的想法是抽象出所有不同硬件和软件制造商之间的架构差异,以便开发人员可以使用一台机器进行写入。
答案 6 :(得分:2)
可以以维护平台独立性的方式编译Java和python。即使对于C#也是如此。优点是VM能够将这种主要强类型的字节码转换为具有相对较低开销的非常好的平台特定代码。由于Java旨在“构建一次 - 在任何地方运行”,因此已经创建了JVM。
答案 7 :(得分:2)
想象一下,你创建了一种编程语言:你想出了语言语义并开发了一个很好的语法。
然而,文本表示是不够的:在执行程序时不得不一次又一次地解析文本是低效的,因此添加内存中的二进制表示是很自然的。结合自定义内存管理器,你基本上有一个VM。
现在,对于额外的点,要么开发一个字节码格式来序列化你的内存中表示和一个运行时加载器,要么就像你想要编写脚本语言一样,eval()
函数。
对于大结局,添加一个JIT。