我读过一些文章说
上述哪一项是正确的?翻译到底是如何发生的,什么是本机代码?是汇编语言代码吗?
我认为这个问题的结构很差,但尝试回答它仍然有价值。
我可以看到您的困惑,问题是 Java 解释器的真正机制实际上与您刚刚阅读解释器的高级描述时想象的完全不同。
首先,Java(或其他基于 JVM 的语言)源代码通过javac编译为字节码。这会产生一个相对简单的.class文件格式,可能包含约 200 个字节码 - 这不是任何真实计算机可以直接执行的格式;相反,它是一种设计为由“虚拟机”(即 JVM)执行的格式。
因此,为了能够在真机上执行编译后的java程序,我们需要将它们“转换”为可执行表示,即机器代码(与本机代码相同)。
默认情况下,JVM 充当解释器:这意味着.class文件一次读取并执行一个字节码(操作码)。解释器的作用是读取操作码并执行相应的操作 - 这就是事情变得更复杂的地方......
通常,您期望解释器有一个大的switch语句,涵盖所有可能的操作码,并根据它遇到的字节码执行适当的操作,例如:
switch (opcode) {
case iconst_1: handleIConst1();
...
}
Run Code Online (Sandbox Code Playgroud)
该代码将是解释器(即 JVM 本身)的一部分,并且会提前编译为机器代码 - 当您安装特定于操作系统的 JVM/JDK 版本时,您会得到这一点。
然而,JVM 解释器是一种特殊类型,称为模板解释器。它不包含硬编码逻辑,但实际上维护了操作码和机器代码之间的映射表。该表在 JVM 启动时填充(您可以通过-> 需要库来查看它)。稍后,当 JVM 开始解释字节码时,解释器将在表中检查是否有与机器代码所在的代码缓存相对应的条目。如果是,则直接执行机器代码;否则它可以回退到动态解析字节码。-XX:+PrintInterpreterhsdis
这样我们就有了一个解释器来逐一执行字节码。此外,如果某些方法“足够热”(调用数千次),还可以使用 JIT。JIT 将启动并取代解释器 - 它将整个方法编译为本机代码,然后在目标计算机上执行。
最后,系统调用的问题与此事无关。任何想要访问硬件或其他敏感资源的程序都必须使用系统调用。它们不是程序的一部分,而是由操作系统提供。
| 归档时间: |
|
| 查看次数: |
1558 次 |
| 最近记录: |