Java程序需经编译→加载→链接(验证、准备、解析)→初始化与执行四阶段:javac生成.class字节码;JVM类加载器载入并构建类结构;链接确保安全合法;最后执行main并可能触发JIT优化。

Java 程序从写好源代码到最终运行,不是直接执行 .java 文件,而是经过“编译 → 加载 → 验证 → 解释/编译执行”这一系列由 JVM 主导的标准化流程。核心在于:Java 是“先编译成字节码,再由虚拟机动态执行”,这带来了跨平台能力,也决定了它的启动和运行机制不同于 C/C++。
1. 编译:javac 将 .java 转为 .class 字节码
Java 源文件(如 Hello.java)不能被操作系统直接运行。需用 JDK 自带的编译器 javac 处理:
- 输入:符合 Java 语法的文本文件(.java),含 public class 定义、main 方法等基本结构
- 输出:与平台无关的二进制字节码文件(.class),内容是 JVM 能识别的指令集(如 iconst_1、astore_0、invokestatic)
- 注意:一个 .java 文件可定义多个类,但只允许一个 public 类,且文件名必须与之完全一致;每个类都会生成独立的 .class 文件
2. 加载:JVM 读入字节码并构建类数据结构
执行 java Hello 命令时,JVM 启动,并通过类加载子系统将 .class 文件载入内存:
- 由 Bootstrap ClassLoader(加载 rt.jar 等核心类)、Extension ClassLoader、Application ClassLoader 分层协作完成
- 加载过程包括:读取字节流 → 创建 Class 对象 → 存入方法区(JDK 8+ 为元空间)→ 生成类的运行时表示
- 此时类尚未初始化,静态变量仅分配内存(设默认值),静态代码块和 static{} 还未执行
3. 链接:验证、准备、解析三步确保字节码安全可用
加载后立即进入链接阶段,保障字节码合法、结构完整、引用正确:
立即学习“Java免费学习笔记(深入)”;
- 验证:检查魔数(0xCAFEBABE)、版本号、常量池格式、字节码逻辑(如跳转是否越界、类型是否匹配)
- 准备:为类变量(static 变量)分配内存并设初始值(如 int=0、Object=null),不执行赋值语句(如 static int x = 5; 此时 x 还是 0)
- 解析:将常量池中的符号引用(如 “java/lang/Object”、“main:([Ljava/lang/String;)V”)替换为直接引用(内存地址或偏移量)
4. 初始化与执行:运行 main 方法,触发即时编译(JIT)优化
当首次主动使用该类(如调用 main 方法)时,JVM 执行初始化,并真正开始运行:
- 执行类构造器 <clinit> 方法:按源码顺序执行所有 static 变量赋值和 static 块
- 调用 main 方法,进入解释执行模式:逐条读取字节码,翻译成当前平台机器指令执行
- 热点代码(频繁执行的方法或循环)会被 JIT 编译器(如 HotSpot 的 C1/C2)编译为本地机器码,缓存复用,大幅提升性能
- 整个过程在运行时数据区(堆、栈、本地方法栈、程序计数器、元空间)协同下完成,GC 同时监控堆内存生命周期
这个过程屏蔽了底层差异,让同一份字节码能在 Windows、Linux、macOS 上无缝运行,也使得诊断问题时需关注编译期错误(javac 报错)、类加载失败(ClassNotFoundException)、运行时异常(NullPointerException)等不同阶段的现象。









