使用Gradle构建Uber(Fat) Jar运行时遇java.lang.NoClassDefFoundError问题排查
排查Gradle构建Fat Jar时Guava未被打包的问题
我来帮你梳理下这个问题,结合你描述的情况——构建成功但运行时找不到Guava,大概率是依赖配置或Fat Jar打包逻辑出了问题,咱们一步步来排查:
1. 先确认Guava的依赖配置是否正确
- 检查你的
build.gradle里Guava的依赖声明:如果是用compileOnly 'com.google.guava:guava:xxx',那Gradle只会在编译阶段使用这个依赖,不会把它打包进Jar包。你需要改成implementation 'com.google.guava:guava:xxx'(把xxx替换成你实际用的版本号),这样Gradle才会将它纳入运行时依赖并打包。 - 要是你用的是多模块项目,还要确认Guava的依赖是不是添加在了最终打包的模块里,或者有没有通过模块依赖正确传递过来。
2. 检查Fat Jar的构建任务配置
不同的Fat Jar构建方式可能有不同的坑:
如果你用的是ShadowJar插件(最常用的Fat Jar插件)
- 查看有没有不小心加了排除Guava的规则,比如:
如果有这条,删掉它就行。shadowJar { exclude group: 'com.google.guava' } - 另外确认
shadowJar任务有没有被绑定到build任务中,比如有没有build.dependsOn(shadowJar),不然执行./gradlew build可能不会触发ShadowJar的打包。
如果你是自定义的jar任务
- 检查你的
jar任务是不是正确收集了所有运行时依赖,正确的配置应该类似这样:
这里要注意用jar { // 收集所有运行时依赖的class文件 from { configurations.runtimeClasspath.collect { it.isDirectory() ? it : zipTree(it) } } // 指定主类(必须,否则运行jar时会找不到主类) manifest { attributes 'Main-Class': 'com.yourpackage.YourMainClass' } }runtimeClasspath而不是compileClasspath,后者只会包含编译时依赖,可能漏掉运行时需要的Guava。
3. 验证Jar包的实际内容
- 构建完成后,手动解压
build/libs/jLocalCoin-0.2.jar,看看里面有没有com/google/guava开头的目录结构;或者用命令行快速检查:
如果没有任何输出,说明Guava确实没被打包进去,回到前面的步骤排查配置;如果有输出,那可能是类加载的问题,但你明确说Guava未被打入,所以先聚焦打包环节。jar tf build/libs/jLocalCoin-0.2.jar | grep guava
4. 查看Gradle构建日志找线索
- 重新执行构建命令并开启日志详情:
仔细查看日志中关于依赖收集、Jar打包的部分,有没有出现类似“Excluding com.google.guava:guava”的提示,或者Guava被标记为“runtimeOnly”但未被纳入打包的信息,这些日志会帮你精准定位问题。./gradlew clean build --info
如果上面的排查都没解决问题,把你的build.gradle完整内容贴出来(特别是依赖声明和Fat Jar构建任务的部分),我可以帮你进一步分析。
内容的提问来源于stack exchange,提问作者djm.im
相关产品推荐
相关产品推荐

