迁移至Gradle 4.5.1(Android Build Tools 3.0.1)遇ClassNotFoundException
刚把项目升级到最新Gradle版本就碰到这种运行时类找不到的问题,确实挺闹心的。我来帮你梳理几个最可能的原因和对应的解决办法:
1. 依赖范围配置错了(最常见!)
如果你的py4j依赖被标记为compileOnly或者testImplementation,那编译阶段能找到类没问题,但运行时这个Jar根本不会被加入类路径,自然就会抛出ClassNotFoundException。
检查你的build.gradle(或build.gradle.kts)里的依赖声明,确保用的是implementation或者runtimeOnly:
// 正确的配置,编译和运行时都会包含该依赖 implementation 'net.sf.py4j:py4j:0.10.6'
避免这种错误配置:
// 错误示例:仅编译时可用,运行时缺失 compileOnly 'net.sf.py4j:py4j:0.10.6' // 错误示例:仅测试阶段可用,主程序运行时缺失 testImplementation 'net.sf.py4j:py4j:0.10.6'
2. Gradle缓存搞鬼了
有时候Gradle的本地缓存可能损坏,或者升级后依赖没有正确刷新。试试清理缓存并重新构建:
# 清理项目构建文件+刷新依赖+重新构建 ./gradlew clean build --refresh-dependencies
Windows用户用这个命令:
gradlew.bat clean build --refresh-dependencies
3. 可执行Jar打包时漏了py4j类
如果你的项目是打包成可执行Jar(比如用Shadow、Jar插件),可能配置里没把py4j的类包含进去。比如用Shadow插件的话,要确保配置里包含了runtimeClasspath的所有依赖:
shadowJar { // 把运行时类路径的所有依赖都打进Jar from configurations.runtimeClasspath mergeServiceFiles() }
如果是用原生Jar插件,也要检查manifest和from配置,确保依赖被正确包含。
4. Java模块系统的遗漏(如果用了module-info.java)
如果你的项目启用了Java模块,必须在module-info.java里声明对py4j模块的依赖,否则运行时找不到类:
module com.yourproject.main { // 声明依赖py4j模块 requires py4j; }
py4j的模块名就是py4j,你可以查看它的Jar包内的module-info.class或者MANIFEST.MF确认。
5. 依赖冲突导致版本被覆盖
虽然py4j 0.10.6确实包含GatewayServer类,但有可能项目里其他依赖间接引入了更低版本的py4j,把你指定的版本覆盖了。可以用这个命令检查运行时类路径里的py4j版本:
./gradlew dependencies --configuration runtimeClasspath | grep py4j
如果输出的版本不是0.10.6,就强制指定版本:
configurations.all { resolutionStrategy.force 'net.sf.py4j:py4j:0.10.6' }
先从依赖范围开始排查吧,这是最容易踩的坑!
内容的提问来源于stack exchange,提问作者M.P.

