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

非Spring Java应用Slf4j+Log4j2打包Jar后报ClassNotFoundException

问题描述

这是一个不含Spring的简单Java应用,带有main方法。使用Lombok的@Slf4j注解,配合log4j2.xml配置文件。Gradle构建文件内容如下:

dependencies {
    ...
    implementation 'org.slf4j:slf4j-api:2.0.7'
    implementation 'org.apache.logging.log4j:log4j-slf4j2-impl:2.20.0'
    ...
}
configurations {
    testImplementation.extendsFrom compileOnly
    // excludes transitive dependencies
    implementation.transitive = false
}
jar {
    dependsOn check
    duplicatesStrategy = DuplicatesStrategy.FAIL

    configurations.implementation.setCanBeResolved(true)

    into('META-INF/lib') {
        from (configurations.implementation)
    }

    manifest {
        attributes("Spring-Context": "*;publish-context:=false")
        attributes(
            'Class-Path': configurations.runtimeClasspath.files.collect { it.getName() }.join(' '),
            'Main-Class': 'com.example.Application'
        )
    }
}

在IntelliJ中运行时日志功能正常,但执行可执行Jar文件时出现以下异常:

Exception in thread "main" java.lang.NoClassDefFoundError: org/slf4j/LoggerFactory
        at dia.nmec.twm.s3_client_plugin.S3ClientPlugin.<clinit>(S3ClientPlugin.java:10)
Caused by: java.lang.ClassNotFoundException: org.slf4j.LoggerFactory
        at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:581)
        at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:178)
        at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:521)
        ... 1 more
解决建议

方法一:打包包含所有依赖的胖Jar(推荐)

用Gradle的Shadow插件直接把所有依赖和应用代码打包到一个Jar中,彻底避免类路径问题:

  1. 在build.gradle中添加Shadow插件:
plugins {
    id 'java'
    id 'com.github.johnrengelman.shadow' version '8.1.1'
}
  1. 配置ShadowJar任务指定主类(若manifest已配置可省略):
shadowJar {
    manifest {
        attributes 'Main-Class': 'com.example.Application'
    }
}
  1. 执行打包命令:./gradlew shadowJar,生成的胖Jar在build/libs/目录下(通常命名为xxx-all.jar),直接运行这个Jar即可。

方法二:修复现有打包逻辑,外置依赖

若不想用胖Jar,调整配置让依赖外置并保证类路径正确:

  1. 移除全局关闭依赖传递的配置:删除implementation.transitive = false,如果需要排除特定传递依赖,针对单个依赖配置exclude,不要全局禁用。
  2. 修改Jar任务和添加依赖复制任务:
jar {
    dependsOn check
    duplicatesStrategy = DuplicatesStrategy.FAIL

    manifest {
        attributes("Spring-Context": "*;publish-context:=false")
        attributes(
            // 给依赖路径添加lib/前缀,对应外置的lib目录
            'Class-Path': configurations.runtimeClasspath.files.collect { "lib/" + it.getName() }.join(' '),
            'Main-Class': 'com.example.Application'
        )
    }
}

// 新增任务:把依赖复制到Jar所在目录的lib文件夹
task copyDependencies(type: Copy) {
    from configurations.runtimeClasspath
    into "$buildDir/libs/lib"
}

// 让Jar打包任务先完成依赖复制
jar.dependsOn copyDependencies
  1. 执行./gradlew jar后,build/libs下会有应用Jar和lib目录,在该目录下执行java -jar your-app.jar即可。

方法三:检查依赖冲突

执行./gradlew dependencies查看依赖树,确认是否有其他依赖引入了冲突的SLF4J版本。如果有,通过exclude排除冲突依赖:

implementation('冲突的依赖坐标') {
    exclude group: 'org.slf4j', module: 'slf4j-api'
}

内容的提问来源于stack exchange,提问作者emiles

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.21 11:47:03