我正在简要阅读Maxine,它是一个用 Java 编写的开源 JVM 实现。这对我来说听起来很循环。如果java需要一个虚拟机来运行,那么虚拟机本身如何用Java编写(VM代码不会需要一个VM来运行,等等?)。
编辑:好的,所以我看到我忽略了 Java 不必在 VM 中运行的事实。那么如何解释如何用 LISP 编写 LISP 编译器呢?或者这应该完全是一个新问题吗?
我正在简要阅读Maxine,它是一个用 Java 编写的开源 JVM 实现。这对我来说听起来很循环。如果java需要一个虚拟机来运行,那么虚拟机本身如何用Java编写(VM代码不会需要一个VM来运行,等等?)。
编辑:好的,所以我看到我忽略了 Java 不必在 VM 中运行的事实。那么如何解释如何用 LISP 编写 LISP 编译器呢?或者这应该完全是一个新问题吗?
您一开始就认为 Java 需要虚拟机是不正确的。查看项目GCJ:Java 编程语言的 GNU 编译器。
引导用 Java 编写的 JVM 所需的 JVM 可能不需要很多功能(例如垃圾收集和 JIT),可能非常简单。然后,所有更高级的功能都可以用 Java 实现(这似乎正是 Maxine 的重点,以试验 JVM 技术中的新想法)。
此外,Maxine 确实包含 C 代码,我猜它构成了一个最小的运行时环境,用于让 Maxine 的其余部分运行。我认为有趣的部分(JIT 编译器,垃圾收集)然后完全用 Java 实现。
请参阅自举。
Java代码可以直接编译成机器码,这样就不需要虚拟机了。
上周我看了 Maxine 并且想知道同样的:)
来自 Maxine文档:
1 构建启动映像
现在让我们构建一个[启动映像]。在这一步中,Maxine 在主机 JVM 上运行以配置原型,然后编译自己的代码和数据,为目标平台创建可执行程序。
2 运行玛克辛
现在 Maxine 已经编译了自己,我们可以将它作为标准 Java VM 运行。max vm 命令处理类和库路径的详细信息,并提供类似于标准 java 启动器命令的接口。
您可以查看完善的引导编译器方法。我认为它始于70年代...
有点“哇哦,伙计,这怎么行???” - 但我认为您正在描述被称为“自托管”的现象:
语言(或工具链/平台)一开始并不是自托管的——它们开始时是在现有平台上构建的:在某一点上,它们变得足够实用,可以编写理解自身语法的程序恰好被写入。
在经典的 AWK 书中有一个很好的例子,它介绍了一个 AWK 程序,它可以解析(一个缩减版)其他 AWK 程序:见下面的链接。
在“Beautiful Code”一书中还有一个例子,它有一个可以解析 Javascript 的 Javascript 程序。
我认为要记住这一点 - 如果你有(比如说)一个用 Java 编写的 JVM,因此可以运行 Java 字节码:运行 Java JVM 本身的 JVM 必须在本地托管(也许这个 JVM 是用'C ' 然后编译为机器代码):在任何情况下最终都是自托管程序 - 沿着这条线的某个地方。
所以这个谜团被消除了——因为在某些时候,有一个本地机器代码程序在所有东西下面运行。
这有点相当于能够使用英语本身来描述英语(等)语言......也许......
我知道这篇文章很旧,但我想我可能会在讨论中添加一些内容,因为它们是被遗漏的要点。因此,未来的读者可能会发现这很有帮助。
我想知道是否每个人都错过了这里的重点。您可以用几乎任何语言编写几乎任何类型的编译器、解释器或虚拟机。当使用 C 编写 C 编译器时,需要 C 编译器来编译新的编译器。但是,输出是在指定平台上运行的本机代码。仅仅因为 JVM 是用在 JVM 上运行的语言编写的,并不意味着输出必须产生在 JVM 上运行的代码。例如,您可以用 Java 编写 C、Basic、Pascal 编译器甚至汇编程序。在这种情况下,您将需要 JVM 来创建编译器或汇编器,但一旦创建,如果初始代码生成本机代码,您可能不再需要 JVM。另一种方法是编写一个翻译器,将输入语言转换为本地机器语言,这样您就可以用语言 A 编写程序,然后将其编译成语言 B,然后再编译成机器代码。在微控制器世界中,您经常看到这一点。有人想用 Basic 或 Java 编写程序,所以他们编写 Basic/Java 编译器来为现有的 C 编译器生成 C 代码。然后将生成的 C 代码编译成提供本地 Basic/Java 编译器的机器语言。这种方法通常比直接用机器代码编写 Basic/Java 编译器更容易。有人想用 Basic 或 Java 编写程序,所以他们编写 Basic/Java 编译器来为现有的 C 编译器生成 C 代码。然后将生成的 C 代码编译成提供本地 Basic/Java 编译器的机器语言。这种方法通常比直接用机器代码编写 Basic/Java 编译器更容易。有人想用 Basic 或 Java 编写程序,所以他们编写 Basic/Java 编译器来为现有的 C 编译器生成 C 代码。然后将生成的 C 代码编译成提供本地 Basic/Java 编译器的机器语言。这种方法通常比直接用机器代码编写 Basic/Java 编译器更容易。
许多年前,我编写了 BasicA 和 GWBasic 程序,它们为 6800 和 Z80 微控制器生成汇编代码。我的观点是,输出不必与输入或目标相同。IE 仅仅因为你在 Java 中编写 JVM 并不意味着最终结果必须在 Java JVM 下运行。
这是一篇关于引导自托管 VM 的好论文。不是Java,而是javascript,但是原理是一样的。
请注意,虽然引导自托管编译器和引导自托管 VM 有点相似,但我相信它们不会引发完全相同的挑战。