Java代码执行过程

Java代码执行过程

在这里插入图片描述
上面这个图片是HotSpot虚拟机架构图,从这张图片中,我们可以清楚地看到,Java代码执行过程。源代码首先编译成class文件,再经由类加载系统加载到内存中,然后由执行引擎执行。

计算机语言发展历史

我们想要了解执行引擎,首先简单了解一下计算机语言地发展历史。最早地计算机语言是机器码,然后发展出汇编语言,又在汇编语言地基础上发展出高级语言。

  1. 机器码
    直接使用0和1组成地二进制表示地指令,最早期地计算机就是使用0和1组成地代码来执行。
    在这里插入图片描述
    早期计算机从业人员就是通过上面图中 利用纸带进行打孔来进行编程,这种编程的过程使用的就是机器码直接进行编程。

机器码是中央处理器 (CPU) 能够直接识别和执行的一组二进制指令。 它是计算机程序执行的最低层次表示。

  • 它由一系列 0 和 1 组成的二进制数字序列构成。

  • 每一个(或一组)特定的二进制模式对应着 CPU 内部电路要执行的一个具体操作,例如:加两个数、从内存加载数据、将数据存储到内存、条件跳转等。

  • 机器码是特定于 CPU 架构的。不同厂商(如 Intel, AMD, ARM, Apple Silicon, RISC-V)或不同世代的 CPU 设计,其机器码指令集通常是不同的。

  1. 汇编语言
    从上面的图中,我们可以清楚的看出来,使用机器码直接进行编程是十分不方便的,可读性很差。于是人们发明了指令。指令就是把机器码中特定的0和1序列,简化成对应的指令(一般为英文简写,如mov、inc等)​,可读性稍好,这就是我们常说的汇编语言。在汇编语言中,用助记符(Mnemonics)代替机器码的操作码,用地址符号(Symbol)或标号(Label)代替指令或操作数的地址。

  2. 高级语言
    为了使计算机用户编程序更容易些,后来就出现了各种高级计算机语言。比如C、C++等更容易让人识别的语言。当计算机执行高级语言编写的程序时,仍然需要把程序解释或编译成机器的指令码。完成这个过程的程序就叫作解释程序或编译程序。
    在这里插入图片描述

Java语言转化过程

从上面的知识中,我们可以清楚的了解到,计算机语言的发展历史。Java语言作为一门高级语言,最终执行的时候也是要转化成机器码。那么这个过程中Java是如何做的呢?
Java语言的编译和执行过程与传统编译型语言(如C/C++)有显著差异,其设计核心是 “一次编写,到处运行”。
Java源代码(.java文件)的编译分为两个核心阶段:

  1. 前端编译(生成字节码):
  • 通过 javac 编译器将Java源码编译成 字节码(Bytecode)(存储在 .class 文件中)。

  • 字节码是JVM的“机器码”,但它是平台无关的中间表示(类似高级汇编,但不是物理CPU的机器码)。

  • 此阶段不涉及传统汇编过程,也不生成物理CPU的汇编代码(如x86或ARM汇编)。

  1. 后端执行(JVM解释与JIT编译):

字节码由JVM加载并执行。执行方式有两种:

  • 解释执行:JVM解释器逐条读取字节码并翻译成本地机器码执行(效率较低)。

  • JIT编译(Just-In-Time Compilation):JVM的热点代码检测器(如HotSpot)会将频繁执行的字节码(热点代码)动态编译为宿主机的本地机器码(如x86汇编 → 机器码)。此时涉及汇编过程:JIT编译器(如C1、C2)在生成机器码的过程中,内部会经过类似“汇编”的步骤,将中间表示(IR)转换为目标平台的汇编指令,最终生成二进制机器码。

为什么会有编译型与解释型?
因为当你有源代码,需要把源代码转化成机器码的时候,这个过程简单理解就是英文翻译为中文的过程。翻译的话,就有实时翻译;和整个文章完整翻译。 完整翻译更能体现文章真实的意思,比如说作者实际上上下文呼应,实时翻译可能就翻不出来;但是完整翻译又不能实时拿到结果。对应到计算机,编译型需要转化整个代码到机器码,所以需要的时间就比较长,而且生成的机器码不具有跨平台性;解释型,开始的时候比较快,但是效率不高,跨平台性较好。

Java解释器

角色与工作方式
  • 角色:Java 程序执行的默认起点。

  • 输入:.class 文件中的字节码 (Bytecode)。

  • 工作流程:

字节码指令
解释器逐条读取
翻译为本地机器码
CPU立即执行
  • 特点:

    • 逐条解释执行:读取一条字节码 → 翻译为机器码 → 执行 → 重复。

    • 无需编译等待:启动速度快,无编译延迟。

    • 跨平台基石:同一份字节码,不同平台的 JVM 解释器能将其翻译为对应平台的机器码。

在这里插入图片描述

Java编译器

核心目标:解决解释器的性能瓶颈

动态编译:在程序运行时,将热点代码 (Hot Spot Code) 直接编译为本地机器码。

热点代码检测:JVM 通过计数器监控方法调用次数和循环回边次数,识别频繁执行的代码。

分层编译(HotSpot JVM 的核心策略)

现代 JVM(如 HotSpot)使用多级编译器协作

方法调用/循环次数达到阈值
代码更热或复杂
解释执行
C1 编译器 编译
C2 编译器 编译
C1 编译器(客户端编译器):
  • 优化目标:编译速度快,提升启动性能。

  • 优化策略:基础内联、简单方法内联、常量传播等轻量优化。

  • 适用场景:对启动速度敏感的应用(如桌面应用)。

C2 编译器(服务端编译器):
  • 优化目标:生成高度优化的机器码,追求峰值性能。

  • 优化策略:

    • 激进内联(如虚方法去虚拟化)

    • 循环展开(Loop Unrolling)

    • 逃逸分析(栈上分配、标量替换)

    • 锁消除(Lock Elision)

  • 适用场景:长时间运行的服务端应用

Graal 编译器(新一代 JIT):

替代 C2,支持更复杂的优化(如部分 AOT 编译)。

需通过 -XX:+UseJVMCICompiler 启用。

JIT 工作流程
JVM 监控 解释器 JIT 编译器 CPU 解释执行字节码 统计方法调用次数 统计循环回边次数 loop [监控热点代- 码] 触发编译(达到阈值) 编译字节码→机器码 替换入口(Code Cache) 直接执行机器码(后续调用跳过解释) JVM 监控 解释器 JIT 编译器 CPU

总结

解释器:保障跨平台性和快速启动,但性能低。

JIT 编译器:运行时编译热点代码,换取接近原生的性能。

协作哲学:“启动阶段用解释器快速执行,运行中逐步编译优化热代码” —— 在跨平台与高性能间取得完美平衡

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ThetaarSofVenice

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值