
本文详解如何通过 gradle 配置生成真正自包含的可执行 jar(即“胖 jar”),解决因 `noclassdeffounderror` 导致的运行失败问题,确保 `gson` 等第三方依赖被完整打包进 jar。
在 IntelliJ 中仅通过「Artifacts → From module with dependencies」导出 JAR 并不能保证所有依赖类被正确合并——尤其当使用 Gradle 作为构建工具时,IDE 的 GUI 打包流程常与 Gradle 的依赖解析机制脱节,导致 com.google.gson.Gson 等类在运行时缺失,抛出 ClassNotFoundException。
正确做法是交由 Gradle 构建一个“Fat JAR”:将项目编译类 + 所有 runtimeClasspath 依赖(如 Gson)一并解压、合并到单个 JAR 中,并自动配置 MANIFEST.MF 的 Main-Class 属性。
以下是关键配置(build.gradle):
plugins {
id 'java'
}
group 'org.example'
version '1.0-SNAPSHOT'
repositories {
mavenCentral()
}
dependencies {
implementation 'com.google.code.gson:gson:2.10.1' // ✅ 使用 implementation(非 compile,已弃用)
testImplementation 'org.junit.jupiter:junit-jupiter-api:5.8.1'
testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.8.1'
}
test {
useJUnitPlatform()
}
// ✅ 关键:定义 fat jar 任务(覆盖默认 jar 任务)
jar {
manifest {
attributes "Main-Class": "org.example.Main" // 替换为你的实际主类全限定名
}
// 将所有 runtime 依赖的 class 文件解压后合并进当前 jar
from {
configurations.runtimeClasspath.collect { it.isDirectory() ? it : zipTree(it) }
}
}✅ 构建与运行步骤:
- 在 IntelliJ 右侧 Gradle 工具窗口中,展开项目 → Tasks → build → 双击执行 jar(或终端运行 ./gradlew jar);
- 输出路径为:build/libs/your-project-name-1.0-SNAPSHOT.jar;
- 终端执行:java -jar build/libs/your-project-name-1.0-SNAPSHOT.jar —— 无需额外 -cp 或外部 JAR。
⚠️ 注意事项:
- 确保 Main-Class 值准确(含包名),且对应类中存在 public static void main(String[]) 方法;
- 若依赖含 META-INF/MANIFEST.MF 或服务文件(如 META-INF/services/),建议改用 shadowJar 插件(com.github.johnrengelman.shadow) 避免资源冲突;
- IntelliJ 的 GUI Artifact 打包应禁用(避免重复构建),以 Gradle 为准,保持构建逻辑统一;
- JDK 17+ 用户需注意:若依赖含非法反射调用,可能需添加 --add-opens 参数,但 Fat JAR 本身不改变 JVM 启动策略。
至此,你获得的是一个真正独立、零外部依赖的可执行 JAR——双击运行或服务器部署均无需额外配置 classpath。










