为什么Java既是编译语言又是解释语言,而JIT也编译字节码?

14

我读到过,Java源代码被编译成“字节码”,然后通过JIT再次编译成“机器码”。也就是说,源代码首先被编译成平台无关的字节码,然后再次编译成特定于机器的代码。那么为什么Java被称为既是解释型语言又是编译型语言呢?解释是在哪里进行的?


1
在您的定义中,根本不存在“解释”的概念 :) 当JIT编译器将代码编译为机器语言时,它会将一堆指令转换并对其进行优化。而解释器只是一次执行一个指令(因此通常要慢得多)。最终,所有东西都必须在机器上运行。(当然,这是一种过度简化,但您明白我的意思) - Benjamin Gruenbaum
https://dev59.com/YXM_5IYBdhLWcg3wjj-r - Supriya
7个回答

19

这里有一些误解。

在正常情况下,Java编译器(javac)将Java代码编译成字节码,然后Java解释器(java)逐行解释这些字节码,将其转换为机器语言并执行。

JIT(即时)编译器是一个稍微不同的概念。JVM维护一个函数被执行的次数计数。如果超过限制,则启用JIT。Java代码直接编译成机器语言,然后用于执行该函数。


这是否意味着整个字节码并非总是进行JIT编译? - Ragul
1
@user3153221 JIT 只识别“热点”并编译它们,它执行优化并存在可能的撤销点。 - Benjamin Gruenbaum
感谢Aniket和Benjamin :) - Ragul

9

Java是一种编程语言。

它有一个规范(JLS),定义了Java程序应该如何运行。

作为一种语言本身,它并没有指定它在不同平台上应该如何执行。它的运行方式,使用JIT还是不使用JIT,完全基于实现。

  • 如果我明天编写一个Java运行时,根本不进行JIT编译,我可以称之为Java解释器。

  • 如果我采用一个将Java字节码作为汇编代码的Java虚拟机(人们真的做过这样的事情),我可以称之为Java严格编译。

很多其他语言也是这样:

  • Python是解释型语言吗?(CPython)还是被JIT编译了吗?(PyPy)
  • Lua是解释型的(旧版Lua解释器)还是被编译的(LuaJIT)?
  • JavaScript是解释型的(IE6样式)还是被编译的(v8)?

2
好观点。对我来说,这应该仍然是一个谜(无论如何),为什么人们会因此感到困惑。这就像“为什么说美元是钱,而欧元也是钱?” - Ingo

3
为了准确起见,让我们明确一点,这不是一个Java编程语言问题,而是JVM的特性。
在JVM最初的实现中,没有JIT,字节码总是被解释执行。这是由于设计决策使得编译代码独立于运行Java的物理机器和操作系统,并且今天仍然有效。
作为后来的改进,JIT被引入JVM实现以加快执行速度,但是字节码必须仍然有效并通过所有验证才能被翻译成二进制。这样您就可以保持平台独立性,所有的健全性和安全性检查,并获得更好的性能。

2

Java是混合语言,即它既是编译型(前期工作)又是解释型(接收端工作)。

字节码是Java的中间语言。Java源代码通过javac编译为字节码。有时,这些字节码再次编译成机器语言,这被称为JIT(即时编译)编译。

JIT编译是执行计算机代码的一种方式,它涉及在程序执行期间-运行时-对代码进行编译,而不是在执行之前。 来源

JVM(没有JIT)将Java中间语言字节码解释为本地机器语言,具体如下:

enter image description here

来源

JVM是一个抽象计算机,它有多个实现:

  • HotSpot(解释器 + JIT编译器):主要参考Java VM实现。被Oracle Java和OpenJDK使用。

  • JamVM(解释器):设计成与其他虚拟机相比非常小。旨在使用GNU Classpath。支持多个架构。GPL许可证。

  • ART(解释器 + AOT编译器,即提前编译):Android运行时是Android操作系统中使用的应用程序运行环境,取代了Dalvik(解释器+JIT编译器)。

Java虚拟机列表


1

javac是一个编译器,它将Java代码转换为字节码(参见字节码),如果我们有JVM(Java虚拟机),则可以在任何计算机上轻松运行。解释器将Java字节码转换为机器码。


0

与其他编程语言不同,Java是一种编译和解释的语言。Java IDE充当编译器,而JVM(Java虚拟机)则像解释器一样运行。也就是说,当任何程序(比如Hello)被保存为Hello.java并编译后,我们会得到一个扩展名为Hello.Class的文件,称为类文件、字节码或中间代码。字节码不依赖于任何特定的机器,因此也被称为中间代码。 为了将这个字节码转换成机器码或机器可理解的格式,需要使用不同操作系统的JVM。JIT(即时编译器)是JVM的一部分,默认情况下启用,可以在“即时”编译字节码为本地机器码。


0

它有两个目的。第一个是确保代码在语法和语义上是正确的。其次,编译过程会产生字节码。正如您所指出的,这是一种与体系结构无关的中间语言,可以由JVM解释或即时编译为特定机器体系结构的本地代码。通过编译成字节码,许多与编译相关的开销可以提前完成,使得JVM能够从已经经过彻底检查和严格验证的字节码生成本地代码或解释字节码。


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