Gradle构建Fat Jar时无法找到主类问题求助
问题:Gradle构建的Fat Jar无法找到主类,自身代码缺失
我为公司开发了一款监控应用,采用Gradle构建,准备分发时发现生成的Jar文件无法运行,报错信息如下:
Error: Could not find or load main class net.nephty.connectwisemonitoring.app.Main Caused by: java.lang.ClassNotFoundException: net.nephty.connectwisemonitoring.app.Main
排查情况
- Main类包含启动main方法,本地运行正常,无编译错误
- 解压生成的Fat Jar后,未找到
net/nephty/...目录及自身代码,但Manifest文件配置正确 - 执行
gradle jar生成的Jar包含自身代码,但不包含第三方依赖
build.gradle内容
plugins { id 'java' id 'application' id 'org.openjfx.javafxplugin' version '0.0.10' id 'org.beryx.jlink' version '2.24.1' } group 'net.nephty' version '1.0-SNAPSHOT' repositories { mavenCentral() } ext { junitVersion = '5.9.0' } sourceCompatibility = '17' targetCompatibility = '17' tasks.withType(JavaCompile) { options.encoding = 'UTF-8' } application { mainModule = 'net.nephty.connectwisemonitoring' mainClass = 'net.nephty.connectwisemonitoring.app.Main' } javafx { version = "18.0.2" modules = ['javafx.base', 'javafx.controls', 'javafx.fxml', 'javafx.graphics', 'javafx.media', 'javafx.swing', 'javafx.web'] } dependencies { implementation('org.controlsfx:controlsfx:11.1.1') implementation('com.dlsc.formsfx:formsfx-core:11.5.0') { exclude(group: 'org.openjfx') } implementation('org.kordamp.ikonli:ikonli-javafx:12.3.1') testImplementation("org.junit.jupiter:junit-jupiter-api:${junitVersion}") testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine:${junitVersion}") implementation group: 'org.seleniumhq.selenium', name: 'selenium-java', version: '4.4.0' } test { useJUnitPlatform() } jlink { imageZip = project.file("${buildDir}/distributions/app-${javafx.platform.classifier}.zip") options = ['--strip-debug', '--compress', '2', '--no-header-files', '--no-man-pages'] launcher { name = 'app' } } jlinkZip { group = 'distribution' } task fatJar(type: Jar) { duplicatesStrategy = DuplicatesStrategy.EXCLUDE manifest { attributes 'Start-Class': 'net.nephty.connectwisemonitoring.app.Main' attributes 'Main-Class': 'net.nephty.connectwisemonitoring.app.Main' } from { configurations.runtimeClasspath.collect { it.isDirectory() ? it : zipTree(it) } } exclude 'META-INF/*.RSA' exclude 'META-INF/*.SF' exclude 'META-INF/*.DSA' } jar { manifest { attributes( 'Main-Class': 'net.nephty.connectwisemonitoring.app.Main' ) } }
环境配置
------------------------------------------------------------ Gradle 7.5 ------------------------------------------------------------ Build time: 2022-07-14 12:48:15 UTC Revision: c7db7b958189ad2b0c1472b6fe663e6d654a5103 Kotlin: 1.6.21 Groovy: 3.0.10 Ant: Apache Ant(TM) version 1.10.11 compiled on July 10 2021 JVM: 17.0.4 (Oracle Corporation 17.0.4+11-LTS-179) OS: Windows 10 10.0 amd64
已尝试操作
参考多篇技术帖子、重构build.gradle、修改重复策略均无效,猜测问题出在fatJar任务的runtimeClasspath配置部分。
解决方案
问题核心是当前的fatJar任务只打包了第三方依赖,没有包含项目自身编译后的class文件。修改fatJar任务,添加sourceSets.main.output即可:
task fatJar(type: Jar) { duplicatesStrategy = DuplicatesStrategy.EXCLUDE manifest { attributes 'Start-Class': 'net.nephty.connectwisemonitoring.app.Main' attributes 'Main-Class': 'net.nephty.connectwisemonitoring.app.Main' } // 加入项目自身编译后的类文件 from sourceSets.main.output from { configurations.runtimeClasspath.collect { it.isDirectory() ? it : zipTree(it) } } exclude 'META-INF/*.RSA' exclude 'META-INF/*.SF' exclude 'META-INF/*.DSA' }
执行gradle fatJar重新构建后,解压Jar文件就能看到自身的代码目录,运行Jar即可正常启动应用。
另外,由于项目配置了Java Module(mainModule),如果后续遇到模块化相关问题,可优先考虑使用jlink任务生成的模块化镜像进行分发,这也是JavaFX应用推荐的分发方式。
内容的提问来源于stack exchange,提问作者Nephty
相关产品推荐
相关产品推荐

