Java类加载机制( 完整生命周期)
Java类加载机制是JVM将类的字节码文件加载到内存并转化为Class对象的过程。主要包括加载、验证、准备、解析、初始化五个阶段。一、类加载的生命周期加载 → 验证 → 准备 → 解析 → 初始化 → 使用 → 卸载链接Linking位于加载Loading和初始化Initialization之间包含了三个子阶段验证、准备和解析。核心任务是将加载进来的类的二进制数据整合到 JVM 的运行时状态中使其可以被执行。缓存机制JVM通过ClassLoader 类全限定名作为缓存的Key保证每个类在每个ClassLoader中只完整加载一次后续使用直接返回缓存的Class对象。类的缓存信息分布在三个区域元空间、堆、以及JVM内部结构。类加载的5个阶段加载、验证、准备、解析、初始化中已经加载过的类不会重新执行整个流程。二、类加载器层次结构双亲委派模型核心原则先向上委派再自己加载工作流程收到加载请求先向上委派给父加载器父加载器继续向上委派直到顶层的启动类加载器从顶层开始尝试加载能加载则返回不能加载则向下传递让子加载器尝试最终都无法加载则抛出异常各加载器职责类加载器加载路径说明Bootstrap$JAVA_HOME/jre/lib/rt.jarC实现JVM内置Extension$JAVA_HOME/jre/lib/ext/*标准扩展APIApplicationCLASSPATH加载应用类Custom自定义路径用户自定义为什么这样设计避免重复加载父加载器加载过的类子加载器不再重复加载保证核心库安全用户无法自定义java.lang.String替换核心类隔离性不同类加载器加载的类相互隔离三、类加载时机主动引用会触发初始化new实例化对象new 实例化对象时如果该类尚未被加载会触发该类的完整加载、连接和初始化过程。访问静态变量/方法访问静态变量/方法是访问类的元数据而类的元数据在类被加载到内存后才会存在。反射调用Class.forName()Class.forName() 默认会触发被加载类的完整初始化包括静态代码块执行、静态变量赋值。子类初始化父类先初始化当初始化一个类时如果它的父类还没有被初始化那么会先递归地初始化父类一直向上到 Object 类。启动类的main方法启动类的main方法会触发启动类即包含main方法的那个类本身的加载被动引用不会触发初始化// 1. 通过子类引用父类静态变量 System.out.println(Child.parentStatic); // 只初始化父类 // 2. 数组定义 Parent[] arr new Parent[10]; // 不初始化Parent new一个数组时只是在创建一个容器对象并没有真正使用到元素类本身的功能。 // 3. 引用静态常量 System.out.println(Class.FINAL_CONST); // 编译期常量已存入调用类常量池 外部访问编译期常量不需要类加载值已内联 内部访问编译期常量也不需要类加载值也被内联 编译期常量的值在编译时就“刻”到了所有使用它的代码里无论内部还是外部运行时不需要原类。准备阶段赋值是为了支持反射、JNI、序列化等需要访问类元数据的场景不是给代码内联用的。四、类加载机制的核心按需加载用到时才加载全权负责加载的类所依赖的类也由同一加载器加载缓存机制加载过的类会缓存双亲委派保证安全性和唯一性沙箱保护隔离恶意代码控制权限