JVM是编译器还是解释器?

90

我有一个关于JVM非常基础的问题:它是一个编译器还是解释器?

如果它是一个解释器,那么JVM内部存在的JIT编译器是什么?
如果两者都不是,那么JVM到底是什么?(我不想要有关JVM将字节码转换为特定机器码的基本定义。)


19
JVM是虚拟机,字节码输入后程序的可观察效果就会出现。其他所有内容都是实现细节。 - user395760
1
是的,没有“the” JVM,有多个规范的实现。 - paxdiablo
@delnan,请把它写成答案。我真的想点赞这样的答案。 - aioobe
@aioobe: 不会。我认为这并不回答这里提出的问题-这是一个非常有用的角度,但问题(在标题和帖子中清楚地说明)明确请求这些实现细节。 - user395760
很好。我认为这确实回答了“如果不是JRE和JDK,那么JVM究竟是什么?”的问题。(因为Java虚拟机更像是规范而不是实现。) - aioobe
7个回答

193

首先,让我们清楚以下几个术语:

  • Javac 是Java编译器 - 将您的Java代码编译为字节码

  • JVM 是Java虚拟机 - 运行/解释/将字节码转换为本地机器码

  • JIT 是即时编译器 - 在运行时将给定的字节码指令序列编译为机器码之前进行编译。它的主要目的是在性能方面做出大量优化。

现在,让我们找到您问题的答案:

  1. JVM:它是编译器还是解释器?

    一个解释器

  2. JVM中存在的JIT编译器呢?

    如果您完全阅读此回复,那么您现在可能已经知道了。

  3. JVM究竟是什么?

    • JVM是驻留在RAM上的虚拟平台
    • 其组件类加载器.class文件加载到RAM中
    • JVM中的字节码验证器组件检查您的代码中是否存在任何访问限制违规。(这是Java安全的主要原因之一)
    • 接下来,执行引擎组件将字节码转换为可执行的机器码

3
你能否告诉我什么是本地代码吗?它是否意味着机器码?我正在尝试学习编译和解释的整个过程,但这些中间术语非常令人困惑。 - Always_a_learner
8
JVM和JIT都将字节码转换为特定于平台的机器码,那么它们之间有什么不同呢?你能广泛解释一下吗? - Aditya
9
“将字节码转换为本地机器代码/解释/运行”是无意义的。它只能执行“解释/运行”或者“将字节码转换为本地机器代码”,而不能同时进行两种操作。 - user207421
1
@RyuCoder VM是一种抽象层。这样,Java编译器在任何平台上生成相同的字节码,因为它在同一个JVM上运行。 JVM正在解释这些指令并仅优化热序列,即经常执行的序列。我们可以将源代码转换为机器代码。 GCC / Clang和其他工具已经做了很多年了。这只是构建事物的另一种方式。例如,通过这种方式,我们可以在ARM上运行在x86等架构上编译的.jar文件,因为它与本地指令集(而不是JVM)分离。 - denis631
1
@RyuCoder,你可以这样做,这就是GCJ、Multi-OS Engine、Graal本地映像等多个JVM实现的方式。这些实现都是有效的JVM实现。这个答案错误地假设解释(可能加强了JIT)是实现JVM的唯一方法。 - cubuspl42
显示剩余9条评论

34

这有点两者兼备,但不是传统意义上的。

现代JVM将字节码编译成本机代码,仅在需要时首次编译。在这种情况下,“JIT”代表“即时”。它从外部充当解释器,但实际上在幕后它正在编译成机器代码。

JVM不应与Java编译器混淆,后者将源代码编译成字节码。因此,将其视为“编译器”并没有多大用处,而是要知道它在后台确实进行了一些编译。


8
@NaeemShah: 我很高兴你喜欢这个答案,并且几乎逐字将其复制到了自己名下的博客文章中。你有权这样做,但根据 StackOverflow 的许可计划,你必须合法地归属于此处,并且你必须按照相同的许可证授权你的博客文章。请查看此网站的页脚,其中链接到以下许可证:http://creativecommons.org/licenses/by-sa/3.0/。也可以参考这篇博客文章:http://blog.stackoverflow.com/2009/06/attribution-required/。 - Mark Peters

12

正如@delnan在评论部分所述,它都不是。

JVM是运行Java字节码的抽象机器。

JVM有几个实现:

  • HotSpot(解释器+JIT编译器)
  • Dalvik(解释器+JIT编译器)
  • ARTAOT编译器+JIT编译器)
  • GCJ(AOT编译器)
  • JamVM(解释器)

...以及许多其他

当谈到JVM时,大多数其他答案都是指HotSpot或上述实现方式的某种组合。


1
ART也是一种解释器:“Android实际上可以通过解释或即时编译(JIT)直接运行.dex代码...” (https://source.android.com/devices/tech/ota/ab/ab_faqs#how-did-you-halve-the-size-of-the-system-partition-without-squashfs) - Irfan Latif

6
它既可以解释字节码,也可以将该字节码编译为本机机器代码(如果它决定值得这样做)。

你可能指的是HotSpot。 - cubuspl42

5

这是两者兼备的。它可以解释字节码,并将其编译为本地代码。


0
Javac是一种编译器,但不是传统意义上的编译器。传统编译器通常将源代码一次性转换为机器级语言以便执行(有关此内容请参见下文)。而JavaC将其转换为字节码而非机器级语言。
JIT是一种Java编译器,同时也充当解释器的角色。传统编译器会将所有代码一次性从源代码转换为机器级语言。相反,JIT逐行执行(逐行执行是解释器的一个特点),并将JavaC生成的字节码转换为机器级语言并执行。具有JIT的JVM有多个实现。Hotspot是Java编程中的主要实现之一。Hotspot实现使JIT通过一次性将重复的代码块转换为机器级语言(如上所述的编译器)来优化执行,以便更快地执行,而不是逐行转换每行代码。
因此,就传统编译器和解释器的典型定义而言,答案并不是非黑即白的。
这是我在阅读了几篇在线答案、博客等后的理解。如果有人有改进这种理解的建议,请随时提出。

-7
JVM同时具有编译器和解释器。编译器将代码编译并生成字节码,然后解释器将字节码转换为机器可理解的代码。
例如:编写和编译程序并在Windows上运行。将.class文件带到另一个操作系统(Unix),由于解释器将字节码转换为机器可理解的代码,因此它也可以运行。

1
你忘了关大写锁定 :) - Aleksej Vasinov
9
首先需要将源代码编译成字节码(与JVM无关),然后JVM会解释这些字节码并将其编译为本机代码(可能不是全部)。 - The_Fox

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