关于传统解释器,编译器和JIT编译器/解释器的说明

我正在学习Java,以下内容对我来说有些混乱。我了解的是:

  • →Java编译器仅将.java程序转换为.class文件,这意味着将我们的源代码转换为字节码(这是使Java平台独立的虚拟机(JVM)的操作码的列表)。

  • →仅“解释”代码,而 没有 将其转换为本地机器代码。它将一条字节码的每条指令作为一条命令一一执行并执行,而不管同一条指令出现多少次。这就是为什么它很慢,Java引入了JIT概念。

  • →这在执行时也会起作用。JIT编译器能够通过缓存已 翻译 的代码块的结果来提高性能-与每次发生时仅重新评估字节码中的每一行或操作数相比,它都可以。

现在我有几个问题:

  1. 由于我的物理处理器仅理解本机代码,因此如何使用JVM的解释器执行Java程序?解释器不会将字节码转换为本地机器代码。除非有人将机器代码放入内存,否则物理处理器将无法执行它。

  2. 假设以某种方式,解释器还将字节码转换为本机代码,那么“区分代码执行与缓存(JIT)和逐行执行(解释器)”是唯一区分JIT和解释器的东西吗?

  3. 如果在执行时,JIT编译器将字节码转换为本机代码(用于执行程序),那么Java为什么不使用提前编译?生成依赖于JVM的字节码(进而使Java平台独立)之后,我们可以将其带到要执行它的目标机器上,然后将其转换为本机机器代码(如创建.exe.out文件) C编译)。这是可能的,因为我们在每个系统上都有一个特定的JVM。这比使用JIT编译要快得多,因为它需要花费一些时间来编译和加载程序。仅通过分配字节码(在从字节码到机器码的最终转换之前生成),它仍将与平台无关。

回答:

免责声明:将所有这些与一粒盐一起食用;这太过简单了。

1:您是对的,因为计算机本身不理解代码,这就是为什么需要JVM本身的原因。假装XY意味着“将堆栈中的前两个元素相加并推入结果”。然后将实现JVM,如下所示:

for(byte bytecode : codeToExecute) {

if (bytecode == XX) {

// ...do stuff...

} else if (bytecode == XY) {

int a = pop();

int b = pop();

push(a+b);

} else if (bytecode == XZ) {

// ...do stuff...

} // ... and so on for each possible instruction ...

}

JVM已在计算机的本机代码中实现了每条单独的指令,并从本质上查找了字节码的每个块以了解如何执行该指令。通过JIT编写代码,可以通过省略这种解释(例如,查找应该如何处理每条指令)来实现大幅度的加速。那,和优化。

2:JIT并没有真正运行代码;一切仍在JVM中运行。基本上,JIT在适当的时候将字节代码块转换为机器代码。当JVM遇到它时,它会认为“哦,嘿,这已经是机器代码了!亲爱的,现在我不必仔细检查每个字节,因为CPU可以自己理解它!我只是抽水,一切都会神奇地自行工作!”。

3:是的,可以通过这种方式预编译代码,以避免早期的解释和JITting开销。但是,这样做会损失一些非常有价值的东西。您会看到,当JVM解释代码时,它还会保留有关所有内容的统计信息。然后,当它对代码进行JIT时,它会知道使用不同部分的频率,从而使它可以在重要的地方对其进行优化,从而使常见的东西更快,而稀有的东西却被牺牲了,从而提高了整体性能。

以上是 关于传统解释器,编译器和JIT编译器/解释器的说明 的全部内容, 来源链接: utcz.com/qa/399822.html

回到顶部