为什么不将所有Java字节码最初解释为机器码?

3
我了解到 Just-in-time compilation (JIT),它有两种实现方式,即解释器和JIT,在运行时都会解释字节码。为什么不预先将所有的字节码解释成机器码,然后开始运行进程,就不再需要解释器呢?
3个回答

6
另一种延迟JIT编译的原因与优化有关: 运行时,虚拟机可以检测到比编译器在编译时能进行更多/其他的可能被优化的模式。JIT在启动时的预编译将始终是静态的,而编译器已经可以完成相同的工作,但通过分析实际运行时行为,虚拟机可能有更多关于可能进行的优化的信息,从而产生更好的优化结果。
例如,虚拟机可以检测到单个代码片段在运行时实际上被执行了一百万次,并执行相应的优化,而编译器可能没有任何信息,就像现代CPU在运行时做出的分支预测一样。
更多信息可以在维基百科上的“自适应优化”文章中找到。

1
此外,它可以对行为进行假设,如果这些假设后来被违反,则可以动态重新编译。这很重要,否则您真的无法内联虚拟函数。 - Antimony
1
+1,但我们在编译器中也有基于配置文件的优化,因此可以在编译时完成类似的操作。 - Lasse Espeholt
“没有什么比真实的东西更好。” ;) - 但是基于配置文件的优化也朝着同样的方向发展。参考链接:http://en.wikipedia.org/wiki/Profile-guided_optimization - JimmyB

4

简单来说,因为要将所有内容预编译成机器码需要一定时间,用户不希望等待应用程序启动。请记住,预编译需要进行许多优化处理,这需要时间。

JVM 服务器版本更加积极地提前预编译和优化代码,因为服务器端的代码往往在进程关闭之前会被执行多次且持续时间更长。

然而,对于 .Net 来说,有一种名为 NGen 的应用程序可以使预编译成为一次性操作,之后就不再需要了。您只需运行此操作一次即可。

并非所有的虚拟机都包含解释器。例如,Chrome 和 CLR (.Net) 在运行之前总是将代码编译成机器码。但是,它们具有多个级别的优化以减少启动时间。


0

我发现链接展示了如何通过运行时重新编译来优化性能并节省额外的CPU周期。

  • 内联扩展:减少过程调用的成本。
  • 删除冗余加载:当两个编译代码产生一些重复代码时,可以通过运行时重新编译来删除它们并进一步优化。
  • 复制传播
  • 消除死代码

这里还有一个链接,提供了与上述相同的解释。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接