类加载器负责将 .class 文件的二进制字节流读入 JVM 并转化为 java.lang.Class 对象。JVM 采用层级化的类加载器体系并通过双亲委派模型确保类加载的安全性和一致性。JVM 预定义的类加载器在 Java 8 及以前的版本中JVM 预定义了三层类加载器启动类加载器 (Bootstrap ClassLoader)实现由 C 编写集成在 JVM 内部不继承自 java.lang.ClassLoader。职责加载核心类库如 JAVA_HOME/lib 目录下的 rt.jar、resources.jar 等或被 -Xbootclasspath参数指定的路径。扩展类加载器 (Extension ClassLoader)实现由 Java 编写派生自 ClassLoader 类。职责加载 JAVA_HOME/lib/ext 目录下的类库或由系统变量 java.ext.dirs 指定的路径。应用程序类加载器 (Application ClassLoader)实现也称为系统类加载器System ClassLoader由 Java 编写。职责加载用户类路径ClassPath上指定的类库。它是程序中默认的类加载器。Java 9 的变化扩展类加载器被重命名为 平台类加载器 (Platform ClassLoader)*。由于引入了模块化系统Project Jigsaw类加载器不再根据 JAR文件路径加载而是根据模块Module进行加载。双亲委派模型这是类加载器体系的核心运作机制。运作流程当一个类加载器收到类加载请求时首先检查该类是否已被加载。若未加载则将请求委派给其父类加载器Parent ClassLoader去完成。此过程向上递归直到最顶层的启动类加载器。如果父加载器无法完成加载在其搜索范围内未找到目标类子加载器才会尝试自己去加载该类。设计目的安全性防止核心 API 被篡改。例如用户自定义的 java.lang.Object不会被加载因为请求会委派至启动类加载器优先加载核心库中的 Object 类。唯一性确保同一个类在不同的类加载器环境下只被加载一次。类加载器的三个核心方法开发者通过继承 java.lang.ClassLoader 实现自定义加载器时需关注以下方法loadClass(String name)实现了双亲委派模型的逻辑通常不建议重写该方法以避免破坏委派机制。findClass(String name)在父加载器无法加载类时被调用。自定义加载逻辑如从数据库或网络获取字节码应实现在此方法中。defineClass(byte[] b, int off, int len)将字节数组二进制字节流转化为 Class 对象。
13.JVM-类加载器体系
类加载器负责将 .class 文件的二进制字节流读入 JVM 并转化为 java.lang.Class 对象。JVM 采用层级化的类加载器体系并通过双亲委派模型确保类加载的安全性和一致性。JVM 预定义的类加载器在 Java 8 及以前的版本中JVM 预定义了三层类加载器启动类加载器 (Bootstrap ClassLoader)实现由 C 编写集成在 JVM 内部不继承自 java.lang.ClassLoader。职责加载核心类库如 JAVA_HOME/lib 目录下的 rt.jar、resources.jar 等或被 -Xbootclasspath参数指定的路径。扩展类加载器 (Extension ClassLoader)实现由 Java 编写派生自 ClassLoader 类。职责加载 JAVA_HOME/lib/ext 目录下的类库或由系统变量 java.ext.dirs 指定的路径。应用程序类加载器 (Application ClassLoader)实现也称为系统类加载器System ClassLoader由 Java 编写。职责加载用户类路径ClassPath上指定的类库。它是程序中默认的类加载器。Java 9 的变化扩展类加载器被重命名为 平台类加载器 (Platform ClassLoader)*。由于引入了模块化系统Project Jigsaw类加载器不再根据 JAR文件路径加载而是根据模块Module进行加载。双亲委派模型这是类加载器体系的核心运作机制。运作流程当一个类加载器收到类加载请求时首先检查该类是否已被加载。若未加载则将请求委派给其父类加载器Parent ClassLoader去完成。此过程向上递归直到最顶层的启动类加载器。如果父加载器无法完成加载在其搜索范围内未找到目标类子加载器才会尝试自己去加载该类。设计目的安全性防止核心 API 被篡改。例如用户自定义的 java.lang.Object不会被加载因为请求会委派至启动类加载器优先加载核心库中的 Object 类。唯一性确保同一个类在不同的类加载器环境下只被加载一次。类加载器的三个核心方法开发者通过继承 java.lang.ClassLoader 实现自定义加载器时需关注以下方法loadClass(String name)实现了双亲委派模型的逻辑通常不建议重写该方法以避免破坏委派机制。findClass(String name)在父加载器无法加载类时被调用。自定义加载逻辑如从数据库或网络获取字节码应实现在此方法中。defineClass(byte[] b, int off, int len)将字节数组二进制字节流转化为 Class 对象。