为什么口译员每次运行程序时都会编译代码?

问题描述 投票:-2回答:2

我的问题是关于所有解释语言,但为了更好地说明我的观点,我将以Java为例。

我对Java的了解是,当程序员编写代码时,他们必须用java字节代码编译它,这类似于通用java虚拟机架构的机器语言。然后,他们可以将代码分发给运行Java虚拟机(JVM)的任何机器。然后,JVM只是一个程序,它接受java字节代码并在每次运行程序时编译它们(针对特定的体系结构)。根据我的理解(如果我错了,请纠正我)如果我运行我的代码,JVM将动态编译它,我的机器将运行编译的指令,当我关闭程序时,所有的编译工作都将丢失,只有要再次完成,第二次我想运行我的程序。这也是一般解释语言速度慢的原因,因为它们必须在每次动态编译。

但是,所有这些对我来说都没有意义。为什么不在我的机器上下载java字节代码,让JVM为我的特定架构编译一次并创建一个可执行文件,然后下次我想运行程序时,我只运行编译后的可执行文件。通过这种方式,java的承诺:“一次编写,随处运行”仍然保留,但没有大部分解释语言的缓慢。

我知道编译JVM时会做一些聪明的动态优化;然而,他们的目的不仅仅是为了弥补解释机制的缓慢吗?我的意思是,如果JVM必须编译一次,运行多次,那么这不会超过JVM所做优化的加速吗?

我想有一些明显的东西我在这里失踪了。有人有解释吗?

java compilation jvm jit interpreted-language
2个回答
1
投票

这是不正确的:

然后,JVM只是一个程序,它接受java字节代码并在每次运行程序时编译它们(针对特定的体系结构)。

JVM包含字节码解释器和优化字节码编译器。它解释程序的字节码,并且出于性能原因仅在必要时将字节码编译为本机代码,以优化代码中的“热点”。

要回答您为什么不存储编译结果的问题,有几个问题:

  • 它需要一个存储它的地方。
  • 它需要处理编译部分中的拼接与不值得编译的部分(或编译整个事物)。
  • 它需要一种可靠的方法来了解缓存的编译代码是否是最新的。
  • 如果程序使用参数X,Y和Z运行,则使用参数A,B和C运行的程序的优化编译代码可能不是最佳的。因此它必须处理这种可能性,要么二次猜测原始编译或记住参数(这将是不完美的:如果它们是文件名或URL,例如,它不会保留其内容),等等。
  • 这在很大程度上是不必要的,编译并不需要那么长时间。将字节码编译为机器代码几乎不需要将源代码编译为机器代码。

所以我认为答案是:它很难且容易出错,所以成本不值得。


0
投票

关于“口译员”做什么的任何此类陈述均受观察,并非所有口译员都是相同的。

例如,Python解释器获取.py源文件并运行它们。在途中,它生成“已编译”的.pyc文件。下次运行相同的.py文件时,如果.py文件尚未更改,则可以跳过“编译”步骤。 (我说自AFAIK以来引号中的“汇编”结果不是机器码)。

现在,转到Java。当然,可以设计Java系统,以便Java编译器输出机器代码模块(或等效地,汇编代码文件),然后可以将其链接到机器特定的可执行映像。但设计师并不想这样做。它们专门用于编译到虚拟机的指令集中,后者解释字节码。

随着时间的推移,JVM已经开始通过将字节码转换为机器代码来优化它们的各个部分。但这与翻译整个程序不同。

关于编译/解释权衡:一个因素是程序执行的时间以及程序在更改之前的时间。如果您正在运行可能仅在更改之前执行一次的简短“学生”程序,那么在编译方面投入很多精力是没有意义的。另一方面,如果您的程序正在控制可能已启动数周的设备,那么设备中的JIT编译是值得的,如果设备重新启动,再次执行它并不是特别麻烦。

编写在一个特定硬件配置上运行的Java代码的一些人可能更喜欢“编译整个事情并完成它”,但这不是这种特定语言采用的方法。我原则上有人可以编写那个编译器,但它的不存在似乎证实没有动力这样做。

© www.soinside.com 2019 - 2024. All rights reserved.