You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.21 14:54:24