Gradle构建模块化Java项目使用uom-systems报模块找不到问题
你排查的问题原因完全准确:tech.units.indriya依赖的javax.inject:javax.inject:1构件本身既没有内置module-info.java模块描述文件,也没有在Jar包的MANIFEST.MF中声明Automatic-Module-Name属性,Gradle在模块化项目构建时默认不会为这类无模块标识的Jar自动生成自动模块,而是直接将其放到类路径的未命名模块中,导致依赖它的模块化组件在模块路径中找不到名为javax.inject的模块,触发编译报错。
你之前直接添加javax.inject依赖后仍然报错,就是因为新增的依赖被Gradle判定为非模块化Jar,没有加入模块路径。
你提到的通过Gradle构件转换为无模块信息的Jar补全模块配置、生成合法自动模块的思路是官方推荐的合规方案,没有兼容性风险,除此之外还有两种可落地的实现,优先选第一种:
方案1:配置构件转换规则(最优,维护成本最低)
直接在build.gradle.kts中添加构件规则,为javax.inject指定固定模块名,Gradle构建时会自动将其包装为合法自动模块加入模块路径,不需要额外调整运行参数,配置如下:
plugins { application } repositories { mavenCentral() } dependencies { // 为缺失模块标识的依赖指定自动模块名 components { withModule<JavaModule>("javax.inject:javax.inject") { moduleName = "javax.inject" } } implementation("systems.uom:systems-common:2.1") implementation("systems.uom:systems-quantity:2.1") implementation("javax.inject:javax.inject:1") } java { modularity.inferModulePath.set(true) } application { mainClass.set("unitsuser.Main") }
另外需要修正module-info.java配置,补充你代码中直接引用的Indriya模块依赖——si.uom.units默认没有传递导出Indriya的包,必须显式声明依赖才能引用对应类:
module unitsuser { requires si.uom.units; requires tech.units.indriya; }
配置完成后直接执行./gradlew run即可正常运行,后续升级uom相关依赖版本也不需要额外调整配置。
方案2:手动指定依赖加入模块路径(适合临时验证)
如果不想配置构件规则,也可以通过编译、运行参数强制将javax.inject加入模块路径,快速验证功能,配置如下:
dependencies { implementation("systems.uom:systems-common:2.1") implementation("systems.uom:systems-quantity:2.1") implementation("javax.inject:javax.inject:1") } tasks.withType<JavaCompile> { options.compilerArgs.addAll(listOf( "--add-modules", "javax.inject", "--module-path", configurations.compileClasspath.get().files { it.group == "javax.inject" }.asPath )) } tasks.withType<JavaExec> { jvmArgs("--add-modules", "javax.inject") }
这个方案不需要修改module-info.java的requires声明,但后续如果新增其他非模块化传递依赖,需要重复添加参数配置,长期维护成本更高。
不建议为了解决这个问题删除module-info.java退化为非模块化项目,会丢失Java模块系统的强封装、依赖校验等能力,上述两种方案都可以在保留完整模块化配置的前提下解决依赖问题。
内容的提问来源于stack exchange,提问作者jlbabilino

