为什么字节码在执行时而不是安装时进行JIT编译?

7

将程序编译成字节码而非本地代码可以实现一定程度的可移植性,只要存在适合的虚拟机就可以。

但我有点想知道,为什么要延迟编译呢?为什么不在安装应用程序时直接编译字节码呢?

如果这样做了,为什么不将其应用于直接编译为本地代码的语言中呢?将它们编译成一个中间格式,在安装程序中分发一个“JIT”编译器,并在目标机器上进行编译。

我唯一能想到的是运行时优化。这大概是唯一无法在安装时完成的主要任务。您有什么想法吗?


如果你更新虚拟机,是否需要重新编译所有程序?或者如果你改变了任何依赖关系,是否需要解决哪些应用程序受到影响并对它们进行重新编译? - jqa
此外,您似乎严重低估了。能够利用CPU的所有最先进技巧而不需要编译20个可执行文件是很好的,但如果程序中存在未解决的动态性,则所有这些都无法帮助提高性能。许多JIT的运行时优化旨在在运行时消除该动态性,当所有所需数据都在那里时。 - user395760
@james:确实是有道理的观点。但对于直接编译成本地代码的语言来说,它们多少都是相同的。也许我只是在寻找一种更容易跨平台分发本地应用程序的方法。 - Xeo
3个回答

1
通常情况下,它是预编译的。例如,可以使用NGEN预编译.NET代码。
不对所有内容进行预编译的一个原因是可扩展性。考虑那些允许在运行时使用反射加载其他代码的语言。

1
一些JIT编译器(例如Java HotSpot)使用基于类型反馈的内联。它们跟踪程序中实际使用的类型,并根据先前看到的内容来内联函数调用,以假设后续也会看到相同的内容。为了使其正常工作,它们需要通过程序的“热循环”运行多次迭代,以了解使用的类型。
这种优化在安装时完全不可用。

0

字节码已经被编译,就像C++代码一样被编译。

此外,JIT编译器,即.NET和Java运行时是庞大而动态的;你无法预测程序使用哪些部分,因此需要整个运行时。

还有一个问题需要认识到,针对虚拟机的语言具有非常不同的设计目标,与针对裸机的语言相比。

以C++和Java为例。

  • C++不能在虚拟机上工作,特别是C++语言设计的很多方面都是针对RAII的。
  • Java由于许多原因不能在裸机上工作,例如基本类型。

编辑:正如delnan正确指出的那样;JIT和类似技术虽然对字节码性能有巨大的好处,但可能在安装时不可用。此外,针对虚拟机的编译与编译成本地代码非常不同。


编译基本上意味着“翻译”(从一种计算机语言到另一种)。将编译器的输出进行编译并没有什么奇怪的地方。 - user395760
@delnan 没错,对我来说 JIT 天才和编译完全不同。我们正在涉及到一些语义问题,我认为这不是 OP 的本意。 - Captain Giraffe
即时编译器是一种编译器,正如其名称所示。它收集输入的方式不同,并且其输出立即执行,它所操作的语言相对于我们使用的语言来说比较低级,但这只是细节问题。所有内部机制,即 JIT 代码的 99% 都是通常的编译器内容 - 分析和优化某些内部表示,然后生成代码。事实上,“传统”编译器的许多优化都被 JIT 编译器借鉴了 1:1! - user395760
@delnan,你让我很好奇。这些优化真的被描述为编译步骤吗?另外,我觉得1:1很难相信,它们应该已经在字节码中实现了。 - Captain Giraffe
针对具有JIT的虚拟机的编译器实际上将大多数优化留给JIT,因为(如果不干扰)它最了解如何进行优化。至少,一些Java和C#大师在各种问题中已经这样陈述过(我会去搜索一些具体的新内容)。至于将它们描述为编译步骤,请参见例如PyPy博客 - user395760
显示剩余5条评论

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