当同时使用JIT编译器时,为什么JVM使用解释器?

问题描述

我们知道,JVM同时使用解释器和JIT编译器。 JIT编译器将重复的那些字节代码转换为机器代码,并将其存储在内存中。现在,当解释器逐行翻译ByteCode并运行它时,对于已转换并存储在内存中的重复代码,它将仅跳过翻译部分,而是直接运行它。从而减少并发冗余转换。

那么,为什么Java在JVM中使用解释器?像JIT这样的编译器可以完成将字节码立即转换为机器码的全部任务吗?

解决方法

事实上,像GraalVM这样的现代Java实现确实提供了将Java字节码的整个类(甚至整个应用程序)编译为本地代码的选项,但是可以提前编译,而不是在运行时编译。肯定有可能实现一个JIT编译器,该编译器在运行时处理整个类,从而完全避免解释。

但是,当您有时间吃完三道菜而GraalVM的本机代码编译器完成了这些工作之后,就很容易理解为什么批量预编译不是默认编译了JVM中的机制。编译本机代码可能会很慢,并且Java并不是天生就可以编译的语言。

大多数JVM提供某种形式的自适应解释/编译平衡,这些平衡在运行时实现。对于重复很多的代码节,解释是“缓慢的”,因为解释工作会重复很多次。对于仅执行一次的代码,编译是“缓慢的”,因为必须在实际执行任何程序指令之前完成编译工作。

因此,现代的Java实现提供了两种策略,并试图平衡它们以在运行时获得最佳的整体性能。概括地说,我们要做的是仅(JIT)编译应用程序的那些部分,这些部分的编译时间成本最大程度地被其带来的好处所抵消。如何做到这一点一直是大量研究的主题,并且不断开发新的方法。

,

this answer中有一个很好的比较,这使我很清楚为什么Java同时使用AOT和JIT。

here中提到的带有JIT的“微调”是在JVM的编译器中完成的,JVM针对其运行的每个系统进行了优化。而且您不会受到链接中列出的不利影响。

,

JRockit JVM没有解释器。即使在进行调试时,它也可以编译所有字节码,因此没有必要。

解释器的一个好处是启动速度更快。例如,静态初始化程序只执行一次,因此通常不需要编译它。

,

解释器允许即时运行并调试代码。 编译器必须进行预编译才能运行,这意味着,如果您的首选环境没有发现错误,则可能需要您进行修复并重新编译该错误。整个项目

因此,它既具有解释器又具有编译器,以提高编译器的速度,并且仍使开发人员能够通过进行小的更改来即时调试并检查修复,而无需每次都重新编译整个项目。

简而言之,最大的原因就是这个。
编译器最终用户的最快运行方式
解释器开发人员最快的调试和编码方式