类加载是对象创建的必要前置条件,JVM必须完成加载、验证、准备、解析、初始化五步后才分配内存构造对象;加载阶段生成Class对象提供元数据支撑;初始化阶段决定静态成员状态,影响实例化行为。

类加载是对象创建的前提,没有完成类加载,就无法创建该类的实例。两者不是并列关系,而是严格的先后依赖:JVM 必须先确保类已加载、验证、准备、解析并初始化完毕,才能为这个类分配内存、构造对象。
类加载是对象创建的必要前置条件
当你写 new Person() 时,JVM 第一步不是分配内存,而是检查常量池中是否存在 Person 的符号引用,以及该类是否已完成初始化。如果没加载过,会立即触发完整的类加载流程(加载→验证→准备→解析→初始化),直到 <clinit>() 方法执行完毕。只有这时,JVM 才认为“这个类准备好被实例化了”。
加载阶段生成 Class 对象,为实例化提供元数据支撑
在加载阶段,JVM 不仅把字节码载入方法区,还会在堆中创建一个 java.lang.Class 实例(比如 Person.class)。这个对象就像该类的“身份证”和“说明书”,记录着字段类型、方法签名、静态变量位置、构造器信息等。后续对象创建时,JVM 正是依据它来:
- 确定对象在堆中要分配多大内存(基于字段数量与类型)
- 知道哪些是非静态字段,需要在对象实例中复制一份
- 找到对应的 <init>() 构造方法入口地址
- 定位父类结构,确保正确执行 super() 链
初始化阶段决定对象的初始状态边界
类的初始化(<clinit>())执行完,才意味着所有 static 成员有了确定值、静态代码块运行完毕。这直接影响对象创建行为:
立即学习“Java免费学习笔记(深入)”;
- 若构造器中用到了某个静态常量(如 public static final int MAX = Config.load();),必须等 <clinit>() 执行完才能取到真实值
- 某些单例模式依赖静态字段持有一个实例,对象创建前该实例可能已被初始化好
- 父类未初始化,子类对象根本无法开始构造——因为 super() 调用会强制触发父类初始化
对象创建过程内嵌类加载检查
哪怕你反复 new 同一个类的对象,每次 new 指令仍会做一次“类加载检查”。不过由于类只初始化一次(同一类加载器下),后续检查会快速通过,直接进入内存分配阶段。这个设计保证了懒加载:类只在真正需要时才加载,不写 new、不调静态方法、不反射,就不会触发加载。


















