我读到,Java 源代码被编译成“字节码”,然后由 JIT 再次“编译”成“机器码”。也就是说,源代码首先被编译成与平台无关的字节码,然后再次编译成特定于机器的代码。那为什么它既被称为解释语言又被称为编译语言呢?口译发生在哪里?
7 回答
这里有一点误解。
一般情况下,java compiler( javac
)将java代码编译成字节码,javainterpreter( java
)逐行解释这些字节码,转换成机器语言并执行。
JIT(Just in time)
编译器是一个有点不同的概念。JVM 维护函数执行的次数。如果超过限制,那么 JIT 就会出现。java代码被直接编译成机器语言,并在那里用于执行该功能。
Java 是一种编程语言。
它有一个规范(JLS),它定义了 Java 程序应该如何操作。
作为一种语言本身,它并没有具体说明它应该如何在不同的平台上执行。它的运行方式,无论使用 JIT 还是不使用 JIT,都是完全基于实现的。
如果我明天编写一个完全不进行 JIT 编译的 Java 运行时,我可以调用 Java 解释。
如果我拿一台使用 Java 字节码作为汇编的 Java 机器(人们认真地制造了这些机器),我可以称 Java 为严格编译。
许多其他语言都是这样做的:
- python是解释性语言吗?(CPython) 还是 JITed (PyPy)?
- Lua 是解释的(旧的 lua 解释器)还是编译的(LuaJIT)?
- JavaScript 是解释的(IE6 风格)还是编译的(v8)?
为了精确起见,让我们明确这不是 Java 编程语言问题,而是 JVM 特性。
在 JVM 的第一个实现中,JIT 不存在并且总是解释字节码。这是由于设计决定使编译代码独立于运行 java 的物理机器和操作系统,并且今天仍然有效。
作为后来的改进,在 JVM 实现中引入了 JIT 以更快地执行,但字节码必须仍然有效并且在转换为二进制之前通过所有验证。通过这种方式,您可以保持平台独立性、所有健全性和安全性检查,并获得性能。
Java 是混合语言,即它既是编译的(预先完成的工作)又是解释的(完成接收端的工作)。
字节码是 Java 的一种 IL(中间语言)。Java 源代码通过javac
. 有时这个字节码会再次编译成机器语言,称为 JIT(Just - In- Time )编译。
JIT 编译是一种执行计算机代码的方法,它涉及在程序执行期间(在运行时)而不是在执行之前进行编译。资源
JVM(无 JIT)将 java 中间语言字节码解释为本机机器语言,如下所示:
JVM是一个抽象的计算机器,它有几种实现:
HotSpot(解释器 + JIT 编译器):主要参考 Java VM 实现。由 Oracle Java 和 OpenJDK 使用。
JamVM (Interpreter) 与其他虚拟机相比,它被开发为一个非常小的虚拟机。设计为使用 GNU 类路径。支持多种架构。GPL。
ART (Interpreter + AOT compiler ie Ahead-of-time compiler) A ndroid R un Time是安卓操作系统用来替代 Dalvik (interpreter + JIT compiler) 的应用运行环境。
javac 是一个编译器,它将 java 代码转换为字节码(参见字节码),如果我们有 JVM(java 虚拟机),它很容易在任何机器上运行。解释器将 java 字节码转换为机器码。
它有两个目的。首先是确保代码在语法和语义上正确。其次,编译过程产生字节码。正如您所注意到的,这是一种与体系结构无关的中间语言,可以由 JVM 针对特定机器体系结构解释或即时编译为本机代码。通过编译为字节码,与编译相关的大部分开销都可以提前完成,让 JVM 从事先经过彻底和严格检查的字节码生成本机代码或解释字节码。
与其他编程语言不同,java 是编译型和解释型语言。Java IDE 充当编译器,而 JVM(Java 虚拟机)的行为类似于解释器。即当任何程序说Hello时,在编译后保存为Hello.java,在编译此文件后,我们得到Hello.Class扩展文件,称为类文件、字节码或中间码。字节码不依赖于任何特定的机器,因此也称为中间码。为了将此字节码转换为机器代码或机器可理解的格式,使用了 JVM,这对于不同的操作系统是不同的。JIT(Just in Time Compiler) 是 JVM 的一部分,默认启用它会将字节码编译为“及时”编译的本机机器代码。