必须确保 module-info.java 中 exports 的包名与源码物理路径严格一致,包括大小写、点号和层级顺序;requires 模块名须与被依赖模块的 module 声明完全匹配;通过 -Xlog:module=debug 或 jdeps 验证导出与依赖关系。
直接看
里
后面写的包名是否和实际源码包结构完全一致——大小写、点号、层级顺序,一个字符都不能错。
确认 exports 包路径与源码物理结构严格匹配
Java 模块系统要求
必须对应磁盘上真实的目录结构:
。如果代码实际放在
(少了一个
r
),模块虽能编译通过,但运行时其他模块 import 该包下的类就会触发
或
。
打开项目资源管理器,逐级展开
源根目录,肉眼核对包路径拼写
特别注意易错点:service / servcie / sevice;util / utils / utill;config / confi;大小写混用如
和
不要依赖 IDE 自动生成的包声明,手动比对最可靠
检查 requires 和 exports 是否成对且指向正确模块
若 A 模块
,而 B 模块想使用它,B 的
中必须有
,且该名称必须与 A 模块的
中
声明完全一致。
在 B 模块中 Ctrl+Click(或 Cmd+Click)
后的模块名,看能否跳转到 A 模块的
如果跳转失败,说明模块名不匹配或 A 模块未被正确识别为模块(比如缺少
或编译输出未包含模块描述符)
确保 A 模块打包为 JAR 时保留了
中的
(如手动设置),或更推荐使用显式模块名
验证运行时模块图是否包含目标包
启动应用时加上 JVM 参数,让 Java 显式打印模块解析过程:
(JDK 9+)可输出模块读取、导出、读取关系
会列出每个类从哪个模块加载,快速定位缺失导出
运行后搜索关键词如
、
、
,直接看到哪一步断开
用 jdeps 工具静态分析依赖与导出关系
在项目构建完成后(如
),用
检查模块间可见性:
查看依赖链
输出最小模块集
重点观察输出中是否有
类提示
这类问题不复杂但容易忽略,关键在“所写即所得”——exports 写什么,源码就必须长什么样,中间没有容错或自动纠正。
module-info.javaexportsexports com.example.service;src/main/java/com/example/service/com/example/servcie/NoClassDefFoundErrorIllegalAccessErrorjavaAPIapiexports com.a.bmodule-info.javarequires a.module.name;module-info.javamodule a.module.name { ... }requiresmodule-info.javamodule-info.javaMETA-INF/MANIFEST.MFAutomatic-Module-Name-Xlog:module=debug--show-module-resolutionexportscom.example.servicenot exportedmvn compilejdepsjdeps --module-path target/*.jar --list-deps your-app.jarjdeps --module-path target/*.jar --print-module-deps your-app.jarerror: module X does not export Y to Z