You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

模块化Java程序运行时ModuleReader无法遍历资源,Jar包运行正常

问题:ModuleReader.list()在直接运行编译代码时无法获取资源文件

项目结构

ProjectName
|
|---src
    |
    |---main
        |
        |---java
        |   |
        |   |---ModuleName
        |       |
        |       |---module-info.java
        |       |
        |       |---PackageName
        |           |
        |           |---Main.java
        |
        |---resources
            |
            |---ResourceParentFolder
                |
                |---ResourceSubFolderA
                |   |
                |   |---Resource1A.png
                |   |---Resource2A.png
                |   |---Resource3A.png
                |
                |---ResourceSubFolderB
                    |
                    |---Resource1B.png
                    |---Resource2B.png
                    |---Resource3B.png

编译并运行的Shell脚本

javac                                        \
        --module-source-path="src/main/java" \
        --module=ModuleName                  \
        -d classes

java                                               \
        --module-path="classes;src/main/resources" \
        --module=ModuleName/PackageName.Main

打包为模块化Jar并运行的脚本

jar                                               \
        --verbose                                 \
        --create                                  \
        --file run/executable/jar/ProjectName.jar \
        --main-class PackageName.Main             \
        -C classes/ModuleName .                   \
        -C src/main/resources .

java                                         \
        --module-path="run/executable/jar"   \
        --module=ModuleName/PackageName.Main

核心疑问

在主方法中调用java.lang.module.ModuleReader的list()方法遍历模块内容:

  • 运行Jar包时能获取ResourceParentFolder下的所有资源
  • 直接运行编译后的代码时,仅返回.class文件

想明确这是模块配置错误,还是ModuleReader.list()仅支持Jar包?已知其他资源获取方式可行,但需了解此方式是否可行,若不可行请说明原因。

已尝试的失败方案

  • 复制src/main/resources到classes目录,未生效;
  • 使用命令javac --patch-module ModuleName=src/main/resources,报错:
error: no source files

解答

原因分析

ModuleReader.list()的行为和模块的封装形式直接相关:

  1. Jar包形式:打包时你把classes/ModuleName的类文件和src/main/resources的资源文件合并到了同一个Jar中,此时整个Jar内的所有文件都属于ModuleName模块的一部分,list()自然能遍历到所有内容。
  2. 松散目录结构:你把classes(存类文件)和src/main/resources(存资源)同时加到--module-path中,Java模块系统会将它们视为两个独立的模块单元——classes下的是ModuleName模块,而src/main/resources会被识别为一个无模块描述符的自动模块,两者完全独立,因此ModuleReader只能读取到ModuleName模块本身的.class文件。

可行解决方案

要让松散目录结构下的ModuleReader.list()能读取到资源,需要让资源文件成为ModuleName模块的一部分,有两种方式:

方案1:编译时将资源复制到模块目录

把src/main/resources下的所有内容直接复制到classes/ModuleName目录下(注意不是复制整个resources目录),让资源和类文件处于同一模块目录中。比如执行:

cp -r src/main/resources/* classes/ModuleName/

之后再运行原Java命令,ModuleReader.list()就能遍历到资源文件。

方案2:运行时用--patch-module挂载资源目录

修改Java运行命令,用--patch-module将src/main/resources的内容“补丁”到ModuleName模块中,命令如下:

java                                               \
        --module-path="classes"                     \
        --patch-module ModuleName=src/main/resources \
        --module=ModuleName/PackageName.Main

--patch-module的作用是将指定路径下的内容合并到目标模块中,此时ModuleReader会把这些资源视为ModuleName模块的一部分,就能遍历到。

关于之前失败尝试的说明

  • 复制整个src/main/resources到classes目录:资源被放到了classes/resources下,而非classes/ModuleName,不属于ModuleName模块的内容,因此无效。
  • 单独执行javac --patch-module ModuleName=src/main/resources:javac需要编译源文件,你只指定了--patch-module但没有传入任何要编译的文件,所以报错error: no source files。正确用法是把--patch-module加到原编译命令中,用于编译时补全模块内容,但对于资源文件来说,运行时补丁更直接。

内容的提问来源于stack exchange,提问作者davidalayachew

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.11 20:40:38