Jenkins生成的部署包导致AWS Lambda抛出ClassNotFoundException
嘿,我之前也踩过几乎一模一样的坑!这种本地正常但CI环境出问题的情况,大概率是构建环境差异或者打包配置的细节没处理到位,咱们一步步来排查解决:
1. 先统一Gradle版本,消除环境差异
本地和Jenkins用的Gradle版本不一致是最常见的“隐形坑”——不同版本的Gradle对依赖打包、任务执行的逻辑可能有细微差别,比如某些插件的默认行为悄悄变了。
解决方法:
在项目根目录通过Gradle wrapper强制指定版本,确保本地和Jenkins用完全相同的Gradle构建:
# 替换成你本地正在用的Gradle版本号,比如6.9.1 ./gradlew wrapper --gradle-version=6.9.1
执行完会生成gradle/wrapper/gradle-wrapper.properties文件,把这个文件提交到代码仓库。Jenkins构建时会自动用这个指定版本的Gradle,不会再依赖系统默认版本。
2. 检查Gradle打包配置,确保依赖全量打入
很多时候本地打包正常是因为手动执行了正确的任务,但Jenkins可能跑错了任务,或者打包脚本没把第三方依赖包含进去。比如你用了shadowJar插件,但配置没覆盖默认行为,或者Jenkins只执行了默认的jar任务(这个任务只会打包你自己写的代码,不会包含依赖)。
正确的打包配置示例(build.gradle):
plugins { id 'java' // 用shadow插件打包包含所有依赖的fat jar id 'com.github.johnrengelman.shadow' version '7.1.2' } java { // 强制指定Java 8,和Lambda运行时完全匹配 sourceCompatibility = JavaVersion.VERSION_1_8 targetCompatibility = JavaVersion.VERSION_1_8 } shadowJar { // 自定义打包后的文件名,方便部署 archiveBaseName = 'lambda-function' archiveClassifier = '' archiveVersion = '' // 确保把项目代码和所有运行时依赖都打进包 from sourceSets.main.output configurations = [project.configurations.runtimeClasspath] } // 让build任务自动依赖shadowJar,这样Jenkins执行build时会生成正确的包 build.dependsOn shadowJar
同时要在Jenkins的构建步骤里确认执行的是./gradlew clean shadowJar(先清理旧产物,再打包),而不是./gradlew jar。
3. 清理Jenkins工作区的残留文件
Jenkins的工作区有时候会残留之前构建的旧文件,导致新打包的ZIP里混入了错误的类或者依赖,引发类找不到的问题。
解决方法:
在Jenkins的构建步骤最开头,先执行./gradlew clean,彻底清理之前的构建产物(包括build目录下的所有文件),再执行打包命令。
4. 确认Jenkins的JDK版本是Java 8
Lambda的Java 8运行时要求字节码是Java 8格式,如果Jenkins用了更高版本的JDK(比如Java 11)编译代码,虽然本地能跑,但Lambda的类加载器可能无法识别新的字节码特性,从而抛出ClassNotFoundException。
解决方法:
- 先确保
build.gradle里已经指定了Java 8的编译版本(上面的配置里已经包含); - 然后在Jenkins的构建节点配置中,为该项目选择Java 8作为JDK,不要用系统默认的JDK。
5. 对比本地和Jenkins生成的ZIP包内容
如果上面的步骤都试过还没解决,那直接把本地生成的ZIP和Jenkins生成的ZIP解压,对比里面的文件结构:
- 看看有没有缺少第三方依赖的jar包;
- 检查你的业务类文件是否存在,路径是否正确;
- 对比META-INF目录下的配置文件有没有差异。
通过对比能快速定位到底是打包时漏了什么,还是文件结构不对导致Lambda找不到入口类。
内容的提问来源于stack exchange,提问作者Heisenberg

