使用Gradle打包含JSch的Jar包时出现NoClassDefFoundError问题求助
I’ve dealt with this exact problem dozens of times—here’s the root cause: the default jar task in Gradle only packages your own code, not external dependencies like JSch. Those dependencies are only used during compilation, so they don’t end up in the final JAR. When you run java -jar, the JVM can’t find JSch’s classes, hence the error.
Let’s get this sorted with two reliable solutions:
Solution 1: Use the Shadow Plugin (Recommended)
The Shadow plugin creates a "fat JAR" that bundles your code and all its dependencies into a single executable JAR. It’s the easiest and most maintainable approach.
Steps:
- Update your Gradle build file to include the Shadow plugin. Replace your existing plugin declarations with this (you can use the latest version if preferred):
plugins { id 'java' id 'java-library' id 'org.junit.platform.gradle.plugin' id 'eclipse' id 'com.github.johnrengelman.shadow' version '7.1.2' }
- Configure the Shadow JAR to set your main class (if you already defined this in the
jarblock, you can skip this—Shadow will inherit it automatically):
shadowJar { manifest { attributes 'Main-Class': '<your-full-main-class-name>' } }
- Build the fat JAR with this command:
./gradlew shadowJar
- Run the generated JAR (it’ll be in
build/libswith a name likeyour-project-name-all.jar):
java -jar build/libs/your-project-name-all.jar
Solution 2: Manually Package Dependencies (For Custom Use Cases)
If you don’t want to use a plugin, you can manually copy dependencies to a folder and configure the JAR’s classpath. This is more work but gives you full control.
Steps:
- Modify your Gradle build file to add a task that copies dependencies, then update the JAR’s manifest:
apply plugin: 'java-library' apply plugin: 'java' apply plugin: 'org.junit.platform.gradle.plugin' apply plugin: 'eclipse' repositories { mavenCentral() } // Copy all compile dependencies to a lib folder task copyDependencies(type: Copy) { from configurations.compileClasspath into 'build/libs/lib' } // Make the jar task depend on copying dependencies first jar.dependsOn copyDependencies jar { manifest { attributes( 'Main-Class': '<your-full-main-class-name>', // Set the classpath to point to the lib folder 'Class-Path': configurations.compileClasspath.files.collect { "lib/${it.name}" }.join(' ') ) } }
- Build the JAR:
./gradlew jar
- Run the JAR—just make sure the
libfolder (with all dependencies) is in the same directory as your JAR:
java -jar build/libs/java_ssh.jar
Why the Default JAR Fails
Gradle’s default jar task is designed to produce a minimal JAR with only your code. Compile-time dependencies like JSch are pulled in during compilation but not included in the final artifact. Without those classes present at runtime, the JVM throws the NoClassDefFoundError when it tries to load JSch.
内容的提问来源于stack exchange,提问作者Kleon

