我正在学习 Java,以下事情对我来说有点困惑。我的理解是:
Java编译器→ Java 编译器只是转换.java
程序进入.class
文件,这意味着将我们的源代码转换为字节码(它是虚拟机(JVM)的操作码列表,这使得 Java 平台无关)。
Java解释器→ 只是“解释”代码并且does not将其转换为本机机器代码。它将字节码的每条指令作为命令逐一执行并执行,无论同一指令出现多少次。这就是它速度慢的原因,Java 引入了 JIT 概念。
即时编译器→ 这也会在执行时发挥作用。 JIT 编译器能够通过缓存已编译的代码块的结果来提高性能。翻译的– 与每次发生时简单地重新评估字节码中的每一行或操作数相比。
现在我有几个问题:
由于我的物理处理器只能理解本机机器代码,因此如何使用 JVM 的解释器执行 Java 程序?解释器不会将字节码转换为本机机器代码。除非有人将机器代码放入内存,否则物理处理器将无法执行它。
假设以某种方式,解释器还将字节码转换为本机机器代码,那么“带有缓存的代码执行块(JIT)和逐行执行(解释器)”是唯一区分 JIT 和解释器的东西吗?
如果在执行时,JIT 编译器将字节码翻译为本机机器代码(用于执行程序),那么为什么 Java 不使用提前编译呢?在生成依赖于 JVM 的字节码(这又使得 Java 平台无关)之后,我们可以将其带到我们想要执行它的目标机器上,然后将其转换为本机机器代码(创建一个.exe
or .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: Yes, 有可能的以这种方式预编译代码以避免解释和 JITting 的早期开销。然而,这样做,你会失去一些非常有价值的东西。您会看到,当 JVM 解释代码时,它还会保留所有内容的统计信息。然后,当它对代码进行 JIT 时,它知道不同部分的使用频率,从而可以在重要的地方对其进行优化,以牺牲罕见的内容为代价使常见的内容更快,从而获得整体性能增益。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)