Java模块化资源读取核心是路径合规+Module API显式访问:资源须置于导出包或模块根目录,跨模块必须用getClass().getModule().getResourceAsStream(),禁用ClassLoader全局查找。

Java 模块化系统中读取资源文件,核心在于路径位置必须合规 + 加载方式必须匹配模块边界。传统 ClassLoader 的 getResourceAsStream 在跨模块场景下容易失效,必须改用 Module API 显式访问。
资源必须放在导出包内或模块根目录
模块系统不支持 exports resources,但资源是否“可见”,取决于它所处的位置:
- 若资源在
src/main/java/com/example/config/app.properties,且module-info.java中声明了exports com.example.config;,则其他模块可用Class.getResource("/com/example/config/app.properties")访问 - 若资源在
src/main/resources/logback.xml(Maven 标准路径),构建后会落到 JAR 根目录,此时不能用Class.getResource("/logback.xml")(它只查导出包路径),而应使用getClass().getModule().getResourceAsStream("logback.xml") - 把资源直接放在
src/main/java/version.txt(即无包结构的平级文件)也可行,它会成为模块根资源,同样通过getModule().getResourceAsStream("version.txt")读取
跨模块必须用 Module.getResourceAsStream,禁用全局 ClassLoader
像 Thread.currentThread().getContextClassLoader().getResourceAsStream() 或 getClass().getClassLoader().getResourceAsStream() 在模块化环境下不可靠——它们可能无法穿透模块边界,尤其当目标资源不在调用方模块的导出范围内时。
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
- 正确做法:获取目标类所在模块的引用,再调用其
getResourceAsStream - 示例:假设模块 A 想读模块 B 的
config.json(位于 B 的导出包com.b.config内),A 中应写:InputStream is = SomeClassInB.class.getModule().getResourceAsStream("com/b/config/config.json"); - 注意路径写法:不加前导斜杠(
/),因为这是相对于模块根的路径;加了反而会失败
避免常见陷阱:路径、编码与构建一致性
很多问题其实不是模块机制本身导致,而是路径组织或构建配置没对齐:
立即学习“Java免费学习笔记(深入)”;
- Maven 项目中,
src/main/resources下的文件默认复制到target/classes/根目录,不是子包;若误以为它属于某个包,用错路径就会返回 null - 用
getResource获取 URL 后转 File,仅适用于开发环境(IDE 或未打包运行),JAR 包内该方式会抛FileNotFoundException;生产环境一律走getResourceAsStream - 路径含中文时,
URL.getPath()返回的是 URL 编码格式(如%E4%B8%AD%E6%96%87.txt),需用URLDecoder.decode(url.getPath(), "UTF-8")解码才可安全构造 File(但再次强调:JAR 内不建议走 File)
模块化资源读取不复杂,但容易忽略路径归属和加载主体这两个关键点。只要资源放对位置、用对 API,跨模块访问就能稳定可靠。

















