我一直在研究编程语言是如何工作的,其中一些语言有一个所谓的虚拟机。我知道这是在另一种编程语言中对编程语言进行仿真的某种形式,并且它的工作方式与使用堆栈执行编译语言的方式相同。我做对了吗?
根据我所做的附带条件,我觉得许多非编译语言允许使用“自由”类型系统的变量。例如,在Python中,我可以这样写:
x = "Hello world!"
x = 2**1000
字符串和大整数完全不相关并占用内存中不同的空间量,那么这些代码如何在基于堆栈的环境中表示?这到底发生了什么? x是否指向堆栈中的新位置并且旧的字符串数据未被引用?这些语言不使用堆栈吗?如果没有,它们如何在内部表示变量?
答案 0 :(得分:7)
可能您的问题应该标题为“动态语言如何工作?”
这很简单,它们将变量类型信息与它一起存储在内存中。这不仅在解释或JIT编译语言中完成,而且还在Objective-C等本地编译语言中完成。
答案 1 :(得分:2)
在大多数VM语言中,变量可以概念化为堆中内存的指针(或引用),即使变量本身位于堆栈中也是如此。对于具有基本类型的语言(例如,Java中的int和bool),它们也可以存储在堆栈中,但不能动态地为它们分配新类型。
忽略原始类型,堆栈中存在的所有变量都将其实际值存储在堆中。因此,如果您动态地为它们重新赋值,则放弃原始值(并通过一些垃圾收集算法清理内存),并将新值分配给新的内存位。
答案 2 :(得分:2)
VM与语言无关。任何语言都可以在VM上运行(Java VM已经有数百种语言)。
VM可以运行不同类型的“汇编语言”,这种语言更适合编译器。在VM中完成的所有操作都可以在CPU中完成,因此将VM视为CPU。 (有些实际上是用硬件实现的。)
它的级别非常低,并且在很多情况下基于堆栈 - 而不是寄存器,机器级数学都相对于相对于当前堆栈指针的位置。
使用常规编译语言,单个步骤需要许多指令。 a +可能看起来像“从相对于堆栈指针的点抓取项目到reg a,抓住另一个到reg b。添加reg a和b。将reg a放入相对于堆栈指针的位置。
VM通过一条简短的指令完成所有这一切,可能是一个或两个字节,而不是机器语言中的4或8字节PER INSTRUCTION(取决于32或64位架构),这些(猜测)应该意味着大约16或32 x86的字节,用于1-2个字节的机器代码。 (我可能错了,我的最后一个x86编码是在80286时代。)
Microsoft在其办公产品中使用(可能仍然使用)虚拟机以减少代码量。
创建VM代码的过程与创建机器语言相同,本质上只是一种不同的处理器类型。
虚拟机还可以实现与语言密切相关的自身安全性,错误恢复和内存机制。
我的一些描述是摘要和记忆。如果你想自己探索字节码定义,那就很有趣:
http://java.sun.com/docs/books/jvms/second_edition/html/Instructions2.doc.html
答案 3 :(得分:1)
许多“如何处理这类或那样的变量”的关键真正归结为元数据......存储然后更新的元信息使VM更好地处理如何分配然后执行正确的变量。
在许多情况下,这是可以真正妨碍性能的开销类型。然而,现代实施等在做正确的事情方面已经走了很长的路。
至于你的具体问题 - 将变量视为vanilla对象/等等......归结为重新分配/重新评估新任务的元信息 - 这就是为什么x可以看起来然后是下一个。
答案 4 :(得分:1)
要回答部分问题,我建议使用google tech talk about python,其中一些有关动态语言的问题会得到解答;例如变量是什么(它不是指针,也不是引用,但是在python的情况下是标签)。