模块化系统不提供exports resources语法,但资源访问受模块路径和加载方式严格约束:必须置于导出包内或模块根目录,并通过Module.getResourceAsStream()显式读取,禁用ClassLoader全局查找。

模块化系统对资源文件(如配置文件、图片、JSON、properties 等)的访问没有像类那样严格的 exports 语法控制,但它通过模块路径(--module-path)和类加载器行为施加了隐性限制——资源默认“不可见”,除非路径组织合规、加载方式得当。
资源文件必须放在导出包内或模块根目录下才易被其他模块定位
Java 模块系统不提供 exports resources 这类指令,但资源能否被跨模块读取,取决于它是否位于一个被 exports 的包中,或是否在模块根路径可被类加载器发现。
- 若资源放在
src/main/java/com/example/config/app.properties,且com.example.config已在module-info.java中声明exports com.example.config;,则其他模块可通过Class.getResource("/com/example/config/app.properties")安全访问 - 若资源放在
src/main/resources/logback.xml(Maven 标准路径),它会被复制到模块 JAR 的根目录;此时需用Module.getResourceAsStream("logback.xml")(而非Class.getResource),因为Class加载器默认只查本模块导出路径下的资源 - 把资源直接放在
src/main/java/下(如src/main/java/version.txt)是可行的,只要该路径不在任何包结构里——它会成为模块根资源,可用Module.getLayer().configuration()...或更实用的getClass().getModule().getResourceAsStream("version.txt")
跨模块读取资源必须用 Module API,不能依赖 ClassLoader 默认行为
传统非模块项目常用 Thread.currentThread().getContextClassLoader().getResourceAsStream(...),但在模块化环境下,该类加载器可能无法跨越模块边界查找资源,尤其当目标资源不在调用方模块的导出范围内时。
在调试 Java 后端 API 故障时使用此技能,尤其适用于以下任务:分析日志、跨 Controller、Service 和 Mapper 层追踪请求、定位异常根因、检查 SQL 执行或参数流转,以及生成简洁的诊断结论与修复方案。
- 推荐方式:获取目标模块引用后,显式调用其
getResourceAsStream方法
示例:Module targetModule = Class.forName("com.example.config.ConfigLoader").getModule();<br>InputStream is = targetModule.getResourceAsStream("config.json"); - 若资源在第三方模块(如
com.fasterxml.jackson.core)中,且未导出含资源的包,即使文件物理存在也无法直接访问——这是设计使然,不是 bug - Maven 构建时确保
resources目录内容正确进入模块输出(检查生成的 JAR 是否包含对应路径),否则getResourceAsStream返回null
动态资源访问受模块图约束,需配合 JVM 启动参数临时开放
某些框架(如 Spring Boot 2.7+ 模块化启动、Log4j2 插件扫描)会在运行时尝试反射加载或遍历模块内资源,此时可能触发 IllegalAccessException 或返回空流。这不是资源不存在,而是模块边界拦截了类加载器的递归查找。
立即学习“Java免费学习笔记(深入)”;
- 安全调试手段:启动时添加
--add-opens java.base/java.lang=ALL-UNNAMED(常见基础需求),或针对具体模块:--add-opens com.example.app/com.example.resources=other.module - 生产环境不建议长期依赖
--add-opens,应推动资源所在模块主动导出资源包(哪怕只是空包),或改用服务接口封装资源读取逻辑 - 验证资源是否可达:在目标模块内写个简单工具方法,返回
this.getClass().getModule().getResources("META-INF/MANIFEST.MF"),观察枚举结果数量
模块化下资源访问的关键不在“绕过限制”,而在于让资源路径与模块契约对齐——它不禁止访问,只拒绝模糊路径和隐式依赖。


















