升级Gradle 7.3与JDK17后启动报Module not found异常如何解决
问题根因
Gradle 7.x 对JDK9+引入的JPMS模块系统做了默认行为变更:只要项目中存在module-info.java文件,构建和启动流程就会严格区分模块路径(module path)和类路径(classpath)。implementation fileTree(include: ['*.jar'], dir: 'libs')引入的本地JAR默认只会被加载到类路径,不会自动加入模块路径。JVM在模块模式下启动时,只会扫描模块路径下的依赖,类路径下的JAR不会被模块系统识别,直接抛出模块找不到的异常。
解决方案
根据项目实际需求选对应方案即可:
- 方案1:强制将本地libs下的JAR加入模块路径
在对应模块的build.gradle中添加如下配置,适配Gradle 7.x的模块路径规则:
这个配置不会改动原有依赖逻辑,只是把libs目录下的JAR补到编译和运行时的模块路径里,改造成本最低。// 运行时补全模块路径 run { doFirst { def libJars = fileTree(dir: 'libs', include: ['*.jar']).files.join(File.pathSeparator) jvmArgs += ["--module-path", libJars] } } // 编译阶段补全模块路径 tasks.withType(JavaCompile) { doFirst { def libJars = fileTree(dir: 'libs', include: ['*.jar']).files.join(File.pathSeparator) options.compilerArgs += ["--module-path", libJars] } } - 方案2:给无模块声明的传统JAR配置自动模块名
如果libs下的JAR是没有内置module-info.class的老版本JAR,就算加入模块路径,JVM也会因为它没有合法模块名无法识别,需要给这类JAR指定固定模块名:- 把报错提示找不到的模块名,和对应JAR做映射
- 在构建配置里给JAR注入
Automatic-Module-Name清单属性,示例配置:
jar { manifest { attributes 'Automatic-Module-Name': 'foo' // 多个JAR的话按实际模块名逐个配置即可 } } - 方案3:关闭JPMS模块模式(适合无模块化需求的老项目升级)
直接删除项目所有模块下的module-info.java文件,Gradle会自动回退到传统类路径模式,不再校验模块路径,原有implementation fileTree的配置可以直接生效,不需要额外改其他配置,启动时也不会再抛出模块相关异常。
注意事项
- 改完配置必须执行
gradle clean清空旧构建缓存,否则旧的路径缓存会导致配置不生效 - 不要把同一个JAR同时放在类路径和模块路径下,否则会触发重复模块异常
- 如果是用SpringBoot等框架打可执行FatJar,需要确认打包插件版本适配JDK17和Gradle7.x,避免打包时漏掉模块路径配置
内容的提问来源于stack exchange,提问作者Vyshakh K J
相关产品推荐
相关产品推荐

