本质是JPMS中exports声明失效,目标模块未被识别为合法消费者;需逐层验证模块是否加载、requires拼写是否精确匹配、是否混用模块路径与类路径、exports是否覆盖正确包路径。

这个问题本质是 Java 模块系统(JPMS)中 exports 声明失效,导致目标模块根本“收不到”导出的包——不是权限没开够,而是对方压根没被识别为合法消费者。排查需从模块依赖链的起点开始逐层验证。
确认目标模块是否在运行时被加载
Java 不会报错“找不到模块名”,而是静默跳过未解析的 requires。先验证目标模块是否真实存在并已加载:
- 运行
java --list-modules | grep -i "目标模块名",看是否出现在模块列表中 - 若使用自定义模块路径(
--module-path),检查该路径下是否存在对应 JAR 或模块目录,且文件名/目录名与module-info.java中声明的模块名完全一致(含大小写) - 启动时加参数
--show-module-resolution,观察日志中是否有require failed: module 目标模块名 not found类提示
核对 requires 语句的模块名拼写与版本兼容性
requires 必须与提供方模块的 module-info.java 中 module xxx.yyy 声明的名称**逐字符匹配**,且不能带版本号:
- 错误示例:
requires com.example.util@1.2;(JPMS 不支持在 requires 中写版本) - 错误示例:
requires com.example.util;但提供方实际声明为module com.example.util.core { ... } - 若提供方模块使用了多版本 JAR(Multi-Release JAR),确保运行时 JDK 版本 ≥ 模块所声明的最低版本,否则模块可能被忽略
检查模块路径与类路径混用冲突
当项目同时使用 --module-path 和 -cp(或 --class-path)时,JVM 会将类路径上的内容视为“未命名模块”,它无法被具名模块通过 requires 显式依赖:
- 如果目标模块实际在 classpath 上(比如旧版 Spring Boot 打包方式),则
requires无效,应改用requires static+ 运行时反射,或迁移到纯模块化部署 - 执行
java --describe-module 目标模块名,若返回Module xxx not found,说明它不在模块路径上;若返回no module descriptor,说明它是自动模块(automatic module),此时requires可用,但模块名取自 JAR 文件名(不含扩展名),需严格对应
验证 exports 语句是否覆盖正确包路径
exports 是按包(package)粒度控制的,且不递归包含子包:
- 若提供方写
exports com.example.util;,则com.example.util.helper中的类仍不可见,需额外写exports com.example.util.helper; - 若消费方尝试访问的是
public类中的protected成员,还需确认该类是否在exports的包内——exports控制的是“包可见性”,不是“成员可见性” - 使用
jdeps --list-deps --module 目标模块名查看该模块实际依赖了哪些其他模块,辅助判断是否遗漏了间接依赖

















