Skip to content

Shadow 插件(Fat JAR)

Shadow 插件(com.github.johnrengelman.shadow)可以将所有依赖打包进一个可执行 JAR,是 Java 命令行工具的标准打包方式。

基本配置

kotlin
plugins {
    application
    id("com.github.johnrengelman.shadow") version "8.1.1"
}

application {
    mainClass.set("com.example.Application")
}

tasks.named<com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar>("shadowJar") {
    // 默认 classifier 为 "all",生成 my-app-1.0-all.jar
    archiveClassifier.set("")    // 清除 classifier,生成 my-app-1.0.jar
    
    // 合并服务文件(SPI 需要)
    mergeServiceFiles()
    
    // 合并 META-INF/LICENSE 等文件
    mergeServiceFiles("META-INF/LICENSE")
    
    // 排除不需要的文件
    exclude("META-INF/*.DSA", "META-INF/*.RSA", "META-INF/*.SF")
}

运行 Shadow JAR

bash
# 打包
./gradlew shadowJar

# 运行
java -jar build/libs/my-app-1.0.jar

类重定位(避免冲突)

当你的库与应用依赖了同一库的不同版本时,可以重定位解决冲突:

kotlin
tasks.named<com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar>("shadowJar") {
    // 将 guava 的包名前缀改变,避免与应用使用的版本冲突
    relocate("com.google.guava", "com.example.shaded.guava")
    relocate("com.google.common", "com.example.shaded.common")
}

最小化 JAR

kotlin
tasks.named<com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar>("shadowJar") {
    // 只打包实际用到的类(减小体积)
    minimize {
        exclude(dependency("org.slf4j:slf4j-api"))  // 排除某些不能被 minimize 的库
    }
}

配置 Manifest

kotlin
tasks.named<com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar>("shadowJar") {
    manifest {
        attributes(
            "Main-Class" to "com.example.Application",
            "Implementation-Version" to project.version
        )
    }
}

下一步