Gradle构建Kotlin与Apache Spark 2.3 Fat JAR失效问题咨询
嘿,我之前也踩过类似的坑!哪怕你的代码里完全没用到Spark,只要声明了它的依赖,打包出来的Fat JAR就罢工,这大概率是Spark的传递性依赖冲突或者Fat JAR打包时的类加载/签名问题导致的,下面给你几个针对性的解决方案:
1. 先排除Spark依赖的打包(最直接的临时方案)
既然你当前代码根本没用到Spark,那完全没必要把它和它的一堆依赖打包进Fat JAR里。把Spark依赖标记为compileOnly(Gradle 3.0+)或者provided,这样Gradle只会在编译时识别它,不会把它打进JAR:
dependencies { // 替换成你实际使用的Spark版本和模块 compileOnly "org.apache.spark:spark-core_2.11:2.4.8" // 你的其他依赖... compile "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version" }
改完之后重新执行./gradlew shadowJar(或者你用的其他打包命令),应该就能正常运行了。
2. 排查传递性依赖冲突
Spark自带很多依赖(比如Guava、Jackson、Log4j等),这些库的版本可能和你项目中隐式依赖的版本不一致,打包成Fat JAR后就会出现类版本冲突,导致运行时抛出NoSuchMethodError或者ClassNotFoundException。
你可以用Gradle命令查看依赖树,找出冲突的库:
./gradlew dependencies
找到冲突的依赖后,在Spark依赖里排除掉冲突的模块,比如排除旧版本的Guava:
dependencies { compile "org.apache.spark:spark-core_2.11:2.4.8" { exclude group: 'com.google.guava', module: 'guava' } }
3. 调整Fat JAR打包插件的配置
如果你用的是Shadow插件(最常用的Fat JAR插件),Spark依赖里的签名文件(META-INF/*.SF、*.DSA、*.RSA)会导致打包后的JAR验证失败。可以在Shadow配置里排除这些文件:
shadowJar { exclude 'META-INF/*.SF' exclude 'META-INF/*.DSA' exclude 'META-INF/*.RSA' // 如果你不需要打包Spark,也可以直接排除整个Spark依赖 dependencies { exclude(dependency("org.apache.spark:spark-core_2.11:2.4.8")) } }
4. 检查Kotlin与Spark的版本兼容性
你当前用的Kotlin 1.2.40是比较老的版本,Spark 2.x系列对Kotlin的兼容不算完美,哪怕没直接调用Spark API,也可能因为依赖库的兼容性问题出问题。建议升级Kotlin到较新的稳定版(比如1.8.x或1.9.x),同时确保Spark版本和Kotlin版本匹配(Spark 3.x对Kotlin的支持更好):
buildscript { ext.kotlin_version = '1.8.22' repositories { mavenCentral() } dependencies { classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" } }
先从第一个方案试起,应该能快速解决你的问题,如果之后要用到Spark,再根据实际需求调整依赖和打包策略~
内容的提问来源于stack exchange,提问作者JairoV

