JDK 9模块化系统未推翻双亲委派模型,而是以模块归属判断为第一道筛选,优先查模块再定加载器;模块路径(--module-path)成为新主干,支持具名、自动、匿名三类模块;类加载器分工更清晰且无继承关系,通过显式协作实现模块化加载。

JDK 9 的模块化系统(JPMS)没有推翻双亲委派模型,而是对它做了结构性微调:保留“委托优先”的逻辑骨架,但把“是否委派”和“委派给谁”的决策权,从加载器层级关系转向模块归属判断。核心变化在于——类加载前先查模块,再定路径。
模块优先的委派逻辑
传统双亲委派中,AppClassLoader 收到请求后直接向上委托给 PlatformClassLoader,再至 BootstrapClassLoader。JDK 9 中,AppClassLoader 会先检查目标类是否属于某个已知模块(比如 java.lang.String 属于 java.base 模块),若属于,则跳过常规父委派,直接交由负责该模块的加载器(这里是 BootstrapClassLoader)处理。
- 模块归属判断发生在委派动作之前,是新增的第一道筛选
- 模块路径(--module-path)中的类,优先走模块加载流程;类路径(-cp)中的类仍走传统委派
- 即使 AppClassLoader 的父加载器是 PlatformClassLoader,它也不会盲目委托——模块信息比加载器层级更权威
模块路径取代类路径成为新主干
--module-path 不是 classpath 的简单别名,而是模块系统的入口机制。它支持三类模块源:
- 具名模块:含 module-info.class 的 JAR 或目录,可声明 requires 和 exports
- 自动模块:普通 JAR 被放入模块路径时,JVM 根据文件名生成模块名(如 guava-32.1.3-jre.jar → guava.32.1.3.jre),自动导出所有包
- 匿名模块:来自 classpath 的类,被归入一个共享的、无名的模块,只能读取其他模块,不能被导出或依赖
模块路径让 JVM 在启动时就能构建模块图,实现编译期与运行期的依赖可见性校验。
类加载器分工更清晰,但仍是协作关系
JDK 9 新增了 PlatformClassLoader,专门加载 java.sql、java.logging 等非核心平台模块;BootstrapClassLoader 专注 java.base 等基石模块;AppClassLoader 则聚焦用户模块与类路径资源。三者之间没有继承关系,仅通过 loadClass() 中显式调用实现协作。
- PlatformClassLoader 是 JDK 9 引入的独立角色,不是 ExtensionClassLoader 的改名,它不加载 classpath 内容
- AppClassLoader 默认只加载模块路径下的具名/自动模块,不再默认扫描 classpath(除非显式指定 -cp)
- 反射访问受限类时,必须满足模块的 opens 或 add-opens 声明,否则抛 IllegalAccessException
兼容旧代码的关键设计
模块系统通过“宽松降级”保障向后兼容:
- 未加 module-info.java 的项目仍可运行,JVM 将其视为在匿名模块中
- classpath 上的类能访问模块路径中导出的包(反向不行),维持老项目调用新模块的能力
- 使用 Automatic-Module-Name 清单属性,可为旧 JAR 指定稳定模块名,避免自动命名冲突
这种设计让模块化不是一道开关,而是一条渐进升级的通道。










