JVM-执行引擎
1. 执行引擎是什么
-
执行引擎是Java虚拟机核心的组成部分之一。
-
“虚拟机”是一个相对于“物理机”的概念,这两种机器都有代码执行能力,其区别是物理机的执行引擎是直接建立在处理器、缓存、指令集和操作系统层面上的,而虚拟机的执行引擎则是由软件自行实现的,因此可以不受物理条件制约地定制指令集与执行引擎的结构体系,能够执行那些不被硬件直接支持的指令集格式。
-
JVM的主要任务是负责装载字节码到其内部,但字节码并不能够直接运行在操作系统之上,因为字节码指令并非等价于本地机器指令,它内部包含的仅仅只是一些能够被JVM所识别的字节码指令、符号表,以及其他辅助信息。
-
那么,如果想要让一个Java程序运行起来,执行引擎(Execution Engine)的任务就是将字节码指令解释/编译为对应平台上的本地机器指令才可以。简单来说,JVM中的执行引擎充当了将高级语言翻译为机器语言的译者。
2. 执行引擎是怎么工作的
从外观上来看,所有的Java虚拟机的执行引擎输入、输出都是一致的:输入的是字节码二进制流,处理过程是字节码解析执行的等效过程,输出的是执行结果。
-
执行引擎在执行的过程中究竟需要执行什么样的字节码指令完全依赖于PC寄存器。
-
每当执行完一项指令操作后,PC寄存器就会更新下一条需要被执行的指令地址。
-
当然方法在执行的过程中,执行引擎有可能会通过存储在局部变量表中的对象引用准确定位到存储在Java堆区中的对象实例信息,以及通过对象头中的元数据指针定位到目标对象的类型信息。
3. 代码编译和执行的过程
代码编译和执行的过程
代码从编写到运行需要经过编译和执行两个阶段,具体过程如下:
1. 编译阶段
将高级语言源代码转换为机器可执行的二进制代码,包含四个核心步骤:
1.1 预处理(Preprocessing)
处理源代码中的宏定义、文件包含等指令。例如在C语言中:
#include <stdio.h> // 引入头文件
#define PI 3.14 // 宏替换
预处理器展开头文件内容,替换宏定义,生成纯净的中间代码。
1.2 编译(Compilation)
将预处理后的代码翻译为汇编语言。编译器进行:
- 词法分析:拆分代码为标记(tokens)
- 语法分析:构建抽象语法树(AST)
- 语义分析:检查类型匹配等规则
- 生成中间代码(如LLVM IR)
1.3 汇编(Assembly)
将汇编代码转换为机器码(目标文件)。汇编器处理如:
MOV AX, 5 ; → 二进制指令 B8 05 00
生成.obj
(Windows)或.o
(Linux)格式的二进制文件,包含机器指令和符号表。
1.4 链接(Linking)
合并多个目标文件和库文件,解决外部引用。例如:
printf("Hello"); // 链接到标准库的printf函数
生成最终可执行文件(如.exe
或ELF格式),完成内存地址分配。
2. 执行阶段
操作系统加载可执行文件到内存并运行:
2.1 加载(Loading)
操作系统分配内存空间,将代码段(.text
)和数据段(.data
)载入内存,建立进程控制块(PCB)。
2.2 指令执行
CPU从入口点(如main
函数)开始逐条执行指令:
- 取指:从内存读取指令
- 译码:解析指令操作类型(如加法)
- 执行:ALU执行运算
- 访存:读写数据到寄存器/内存
- 写回:更新寄存器状态
2.3 运行时管理
- 堆栈管理:函数调用通过栈帧传递参数,局部变量存储在栈区
- 动态内存:
malloc
等操作在堆区分配内存 - 异常处理:中断机制处理错误或外部事件
3. 示例流程(C语言程序)
4. 关键概念
- 解释型语言(如Python):跳过编译阶段,通过解释器逐行翻译执行
- 即时编译(JIT):在运行时动态编译热点代码(如Java JVM)
- 交叉编译:在A平台生成B平台可执行文件(如开发嵌入式系统)
此过程确保了代码的跨平台性和执行效率,是计算机系统运行的核心机制。