JDK9后,类加载机制,相较于JDK8以前的双亲委派机制的改变

JDK9类加载机制中的模块优先委派规则解析

一、背景:JDK9的模块化系统(JPMS)

JDK9引入了模块化系统(Java Platform Module System, JPMS),将JDK核心类库拆分为多个模块(如java.basejava.sql等)。这一变化影响了类加载机制,传统的三层类加载器(启动类加载器、扩展类加载器、应用类加载器)在JDK9中演进为:

  • 平台类加载器(PlatformClassLoader):替代原扩展类加载器,负责加载JDK的平台模块
  • 应用类加载器(AppClassLoader):负责加载应用程序的类路径(classpath)资源
  • 启动类加载器(BootstrapClassLoader):仍负责加载最核心的模块(如java.base

二、模块优先的类加载委派规则

在JDK9之前,类加载遵循双亲委派模型:类加载器收到请求后先委派给父加载器,父加载器无法加载时才自己处理。
而JDK9的新规则是:平台类加载器和应用类加载器在委派给父加载器前,会先判断目标类是否属于某个系统模块。若属于,则优先由对应模块的加载器处理,而非直接遵循传统的双亲委派顺序。

三、具体流程解析

  1. 类加载请求触发:当平台类加载器(或应用类加载器)收到加载类X的请求时
  2. 模块归属判断:检查X是否属于某个系统模块(通过模块描述符module-info.class定义)
  3. 模块加载器优先
    • X属于模块M,则由负责加载模块M的加载器处理(通常是平台类加载器或启动类加载器)
    • 若不属于任何模块,则按传统双亲委派模型,先委派给父加载器(平台类加载器的父加载器是启动类加载器)
  4. 父加载器委派:若模块加载器无法处理,再按传统流程向上委派

四、案例说明:以java.lang.String类为例

假设应用程序尝试加载java.lang.String类,流程如下:

  1. 加载器接收请求:应用类加载器(AppClassLoader)收到加载java.lang.String的请求
  2. 模块归属检查
    • java.lang.String属于java.base模块(JDK核心模块)
    • java.base模块由启动类加载器(BootstrapClassLoader) 负责加载
  3. 模块加载器优先处理
    • 应用类加载器不会直接委派给父加载器(平台类加载器),而是先判断该类属于java.base模块
    • 直接委托给负责java.base模块的启动类加载器加载
  4. 启动类加载器加载:成功加载java.lang.String,返回类对象

五、另一个案例:自定义模块与应用类的加载

假设存在以下场景:

  • 模块com.example.util(位于JDK平台模块路径)定义了类com.example.util.Utils
  • 应用程序定义了类com.example.app.App,依赖com.example.util.Utils

加载流程:

  1. 应用类加载器加载App,发现依赖Utils
  2. 检查Utils的模块归属
    • Utils属于com.example.util模块(平台模块)
    • 该模块由平台类加载器(PlatformClassLoader) 负责加载
  3. 平台类加载器处理
    • 平台类加载器先检查com.example.util模块是否已加载
    • 若未加载,则加载该模块并实例化Utils
  4. 依赖注入完成App类成功引用Utils

六、模块优先规则的意义

  1. 强化模块化隔离:确保系统模块中的类只能由对应加载器加载,避免应用程序通过类路径覆盖核心类
  2. 优化加载效率:直接定位模块加载器,减少不必要的父加载器委派
  3. 支持模块化部署:使JDK自身模块与应用模块的加载逻辑更清晰,符合JPMS设计目标

七、与JDK8双亲委派模型的对比

场景 JDK8双亲委派模型 JDK9模块优先规则
加载核心类(如String 应用类加载器→扩展类加载器→启动类加载器 应用类加载器先判断模块归属,直接委派给启动类加载器
加载平台模块类 无模块概念,扩展类加载器加载 平台类加载器优先加载对应模块类
加载应用类 应用类加载器自行处理(父加载器无法加载) 若不属于模块,按传统流程委派

八、总结

JDK9的类加载机制在传统双亲委派模型基础上,增加了模块归属判断的优先级:当类属于某个系统模块时,优先由负责该模块的加载器处理。这一改动是JPMS模块化设计的核心体现,既保证了系统模块的隔离性,又优化了类加载流程。理解这一机制有助于在模块化开发中避免类加载冲突,尤其是在处理自定义模块与JDK核心模块的依赖关系时。

posted @ 2025-06-19 16:00  认真的刻刀  阅读(140)  评论(0)    收藏  举报