为什么java解释代码,如果它可以编译它?

时间:2016-08-23 18:35:07

标签: java compilation jvm jit jvm-hotspot

在企业应用程序中,相同的代码运行数天而没有重新启动,如果代码被多次命中,即超过阈值时间,那么它将被jit编译无论如何(大部分)它所以我想问为什么它不是首先编译的。我的意思是jvm工程师可以将代码编译为字节代码以保持平台独立性,并再对机器代码进行编译,并且在一般情况下不应该使机器代码更快满足jit编译的要求,然后jvm可以使用所有的分析信息和统计信息来增强机器代码并进行所有增强。当然,这将占用编译时间,但是通用代码而不是每次都被简单地执行。即创建一个编译器,在某些方法变得热的情况下编译并夸大它。我可能在这里错了,但这是一个奇怪的问题。

3 个答案:

答案 0 :(得分:1)

使用优化进行编译非常昂贵。查看大型C项目的编译时间(例如firefox,linux kernel),尤其是链接时间优化。

JIT还为目标平台进行编译,即他们尝试使用他们可以支持的所有可用指令进行编译,这意味着您无法分发已编译的代码。

现在考虑JIT执行推测性优化(基于分析),这可能会导致错误并需要摆脱困境。如果仅编译是一个选项,则此代码在重新编译之前将无法继续运行。使用解释器,它可以继续执行导致救助的不常见代码路径。

您还必须记住,某些优化是特定于工作负载的,即(错误的)测试工作负载可能会执行与实际工作负载不同的代码路径,因此在运行时分析后进行不同的编译会从中受益。

并非所有应用程序都是长时间运行的守护进程。有些东西会激活JVM来执行单个任务,然后在完成后退出。

还要考虑很多代码只运行一次,例如在应用程序启动或关闭期间。

所有这些因素都会导致某些 JVM默认使用组合解释器+编译器的原因。其他人可能只使用AOT编译的代码或由于不同的技术权衡而仅使用解释器,但它们通常不会更快。

答案 1 :(得分:0)

它是多种因素和设计选择的混合。

Java以字节码形式提供,并且永久工件不依赖于平台。这是确保平台独立性的设计选择。 Android做出了不同的选择,主要是因为它运行的平台受限制更多。

解释代码比编译代码并运行一次更快。 因此,要在适当的启动时间内获得最佳性能。当您确定需要代码时,启动编译是很有效的。编译在另一个线程中完成,二进制文件准备好后立即使用。当代码经常使用时,Hotspot甚至会进行多次重复编译。它可以使用实际的动态运行时特性,因此二进制文件可以比只有静态信息的任何代码更快。

答案 2 :(得分:0)

Java运行大多数解释的代码,因为大多数代码运行得足够快,并且不需要承担本机编译的开销。 JIT(HotSpot)引擎将优化高度使用的代码,其中支付证明了努力的合理性。此外,它将优化上下文中的 ,这意味着即使变量可能在理论上发生变化,也不会在特定的命令序列中出现,因此序列可以将其置于寄存器中或保持它作为一个常数。当违反假设时,JIT将其重新置于解释模式。提前编译将失去运行时洞察力的所有优势。 Java的方式实际上产生的代码比C ++可以实现的编译语言更紧凑,更高效。