Gradle多项目中子项目可执行Jar主类无法加载问题排查
解决Gradle多项目下Fat Jar无法找到主类的问题
你在Gradle多项目架构里构建可执行Fat Jar时碰到的主类找不到问题,确实大概率出在手动实现的Fat Jar打包逻辑上——普通Jar能正常运行,说明主类本身的路径和代码没问题,只是打包依赖时破坏了类路径结构,导致JVM定位不到主类。
下面给你两种解决方案,优先推荐用成熟的插件来处理,适配多项目的长期扩展需求:
方案一:使用Shadow插件(推荐)
Shadow是Gradle生态里专门用来构建Fat Jar(也叫Uber Jar)的插件,能自动处理依赖冲突、合并重复资源,对多项目架构的支持也很友好,后续新增子项目时能快速复用配置。
配置步骤:
- 在根项目的
build.gradle中添加插件依赖:
plugins { id 'com.github.johnrengelman.shadow' version '8.1.1' apply false }
(版本号可根据你使用的Gradle版本调整,确保二者兼容)
- 在子项目
partition-by-users的build.gradle中应用插件并配置:
plugins { id 'java' id 'com.github.johnrengelman.shadow' } shadowJar { zip64 = true // 保留你需要的zip64配置 manifest { attributes 'Main-Class': 'com.client.dataPipelineJobs.partitionByUsers.PartitionByUsers' } // 可选:自定义Jar名称,比如去掉默认的"-all"后缀 // archiveBaseName.set('partition-by-users') // archiveClassifier.set('') } // 可选:让build任务自动触发shadowJar,执行gradle build时直接生成Fat Jar build.dependsOn shadowJar
- 构建并运行:
从根项目执行构建命令:
gradle shadowJar
生成的Fat Jar会在partition-by-users/build/libs/目录下,默认名称为partition-by-users-<版本号>-all.jar。运行它:
java -jar partition-by-users/build/libs/partition-by-users-<版本号>-all.jar
方案二:修复手动Jar配置(不推荐)
如果不想用插件,你可以尝试修复原来的打包逻辑,核心是确保依赖类被正确打包且不破坏主类路径:
jar { zip64 = true manifest { attributes('Main-Class': 'com.client.dataPipelineJobs.partitionByUsers.PartitionByUsers') } // 先打包当前项目的编译输出 from sourceSets.main.output // 仅打包runtimeClasspath中的Jar依赖,避免重复解压导致的路径混乱 from { configurations.runtimeClasspath.findAll { it.name.endsWith('.jar') }.collect { zipTree(it) } } // 排除冲突的META-INF签名文件,避免打包报错 exclude 'META-INF/*.SF', 'META-INF/*.DSA', 'META-INF/*.RSA' }
不过这种方式长期维护成本高,遇到复杂依赖时还是容易出问题,更推荐用Shadow插件。
额外排查小技巧
- 确认你的Java文件路径是否符合包结构:
PartitionByUsers.java应该放在partition-by-users/src/main/java/com/client/dataPipelineJobs/partitionByUsers/目录下(Gradle默认源码目录是src/main/java,如果你的项目结构特殊,需要在子项目build.gradle中配置sourceSets)。 - 构建后可以用
jar tf <生成的Jar路径>命令查看Jar内部结构,确认com/client/dataPipelineJobs/partitionByUsers/PartitionByUsers.class存在,且META-INF/MANIFEST.MF中的Main-Class配置正确。
内容的提问来源于stack exchange,提问作者Bitswazsky
相关产品推荐
相关产品推荐

