JVM 类加载机制
类加载器(ClassLoader)
类加载器(ClassLoader)在 JVM 体系中扮演着至关重要的角色,它肩负着从文件系统、网络或其他来源加载 Class 字节码文件的使命,并将其精准地转换为 java.lang.Class 对象。JVM 预先内置了三种主要类型的类加载器:
- 启动类加载器(Bootstrap ClassLoader):此加载器由 C++ 语言实现,主要负责加载 <JAVA_HOME>/jre/lib 目录下的核心类库,像 rt.jar 这类关键的库文件便在其加载范畴之内。
- 扩展类加载器(Extension ClassLoader):采用 Java 语言编写实现,它的职责是加载 <JAVA_HOME>/jre/lib/ext 目录下的扩展类库,为 JVM 的功能扩展提供支持。
- 应用程序类加载器(Application ClassLoader):同样以 Java 实现,它负责加载 classpath 下的类,在日常的 Java 开发工作中,它是最为常用的类加载器,为开发者提供了便捷的类加载途径。
类加载过程
- 加载(Loading):借助类的全限定名获取对应的二进制字节流,进而将字节流所表征的静态存储结构巧妙地转化为方法区的运行时数据结构,最终在内存中生成一个能够代表该类的 java.lang.Class 对象。
- 验证(Verification):该步骤旨在确保 Class 文件的字节流严格符合 JVM 规范,杜绝任何潜在的安全隐患,保障系统的安全性与稳定性。
- 准备(Preparation):为类的静态变量分配相应的内存空间,并将其初始化为默认值。例如,对于 int 类型的静态变量初始化为 0,引用类型的静态变量初始化为 null。
- 解析(Resolution):把常量池中的符号引用替换为直接引用,使得程序能够准确地定位和访问相关资源。
- 初始化(Initialization):执行类构造器 <clinit>() 方法,对静态变量进行赋值操作,并执行静态代码块。这是类加载过程的最后一个阶段,在这个阶段,Java 代码才得以真正执行,标志着类开始正式投入使用。
双亲委派模型
工作机制
当某个类加载器接收到类加载请求时,它并不会即刻自行尝试加载该类,而是会优先将此请求委派给其父类加载器去处理。只有当父类加载器在其搜索范围内未能找到该类,从而无法完成加载任务时,子类加载器才会尝试亲自加载该类。
优点
- 避免重复加载:双亲委派模型能够确保在 JVM 中,每个类仅会被加载一次,有效规避了内存中出现多个具有相同全限定名的类的情况,进而优化了内存的使用效率。
- 保障安全性:该模型保证了诸如 java.lang.Object 这类核心类库始终由启动类加载器进行加载,从根源上防止了恶意代码对核心类进行覆盖或篡改,有力地维护了 JVM 运行环境的安全性和稳定性。
缺点
父加载器存在无法访问子加载器路径下类的局限性。以 JNDI、JDBC 等 SPI(Service Provider Interface)机制为例,核心 API 被定义在父加载器所加载的 JAR 包中,然而其具体实现却是由第三方厂商提供,并放置于应用 classpath 之中。在此情形下,就需要父加载器调用子加载器来完成实现类的加载工作。
打破双亲委派模型的场景
SPI(Service Provider Interface)机制
SPI 机制是打破双亲委派模型的典型场景,像 JDBC、JNDI(Java Naming and Directory Interface)、JAXB(Java Architecture for XML Binding)等框架均属此类。在这些框架中,其核心接口由启动类加载器负责加载,然而接口的具体实现则由厂商提供,通常被放置在应用 classpath 里,由应用程序类加载器进行加载。在此情况下,就需要借助线程上下文类加载器(TCCL)来实现“反向委派”。具体而言,父加载器(如启动类加载器)会获取当前的 TCCL(一般为应用程序类加载器),再利用 TCCL 去加载 SPI 接口的实现类。
OSGi (Open Service Gateway Initiative) 框架(如 Eclipse Equinox)
为达成模块化和热插拔功能,OSGi 构建了一套复杂的类加载机制。该机制允许类加载器之间相互进行委派,而并非严格遵循双亲委派模型。这一特性使得 OSGi 框架在动态性和灵活性方面表现卓越,能够更好地适应不断变化的应用需求。
热部署/热插拔
以 Tomcat 服务器为例,它会为每个 Web 应用创建一个独立的类加载器,以此实现不同应用之间的隔离以及热部署功能,这无疑打破了双亲委派模型。当某个 Web 应用需要重新部署时,只需销毁旧的类加载器并创建新的类加载器即可,这种方式极大地提高了应用更新的效率和便捷性。