JPMS运行时如何确定根模块以构建模块图
JPMS运行时模块图构建的根模块确定规则
你之前的认知存在两处初学者常见偏差,以下是完整的规则说明:
默认根模块集合的判定
默认情况下模块路径上的所有模块并不会被全部加入根模块集合,根模块的默认范围和启动方式直接相关:
- 启动模块化应用时(通过
java --module <初始模块>/<主类全限定名>命令启动):只有命令行指定的初始模块会被加入默认根模块集合 - 启动非模块化应用时(主类从类路径加载):只有核心基础模块
java.base会被加入默认根模块集合,其余JDK内置模块、模块路径上的自定义模块都不会默认进入根集合
自定义根模块集合的方式
你提到的--add-modules参数是修改根模块集合的核心方式,它除了支持指定具体模块名,还有几个常用特殊值:
--add-modules <模块1>,<模块2>:将列出的显式模块直接加入根模块集合--add-modules ALL-MODULE-PATH:将模块路径上所有可观测的模块全部加入根模块集合,这也是你之前认知里“模块路径模块全进根集合”的场景,属于参数显式指定的行为而非默认逻辑--add-modules ALL-SYSTEM:将所有JDK内置的系统模块加入根模块集合--add-modules ALL-DEFAULT:将JDK默认隐式加载的系统模块集合加入根,常用于注解处理、编译插件类场景
模块图构建与类路径回退逻辑
确定根模块集合后,JPMS会递归解析所有根模块在module-info.java中声明的requires依赖,把整条依赖链上的模块都加入模块图,没有被依赖链覆盖到的模块,哪怕放在模块路径上也不会被加载进模块图。
关于类加载和未命名模块的逻辑,你之前的理解基本准确,补充两个细节:
- 只有当模块图内所有已解析模块都找不到目标类时,JPMS才会回退到类路径搜索
- 类路径下加载到的所有类都归属于全局唯一的未命名模块,这个模块不需要手动声明,默认拥有读取所有已解析命名模块的权限;未命名模块本身不会自动进入根模块集合,只有实际触发类路径上的类加载时,对应类才会被加载到未命名模块中。
常见踩坑:很多初学者把第三方模块放到模块路径后依然报
ClassNotFoundException,本质原因就是这些模块既没有被初始模块requires声明依赖,也没有通过--add-modules加入根集合,压根没有被解析进模块图。
内容的提问来源于stack exchange,提问作者askaquestion
相关产品推荐
相关产品推荐

