
Jar 包替换内部依赖后 ClassNotFoundException 问题排查
问题描述
在维护 Spring Boot 项目时,需更新外部 Jar 包 app.jar 中 BOOT-INF/lib/ 目录下的内部依赖 core-service.jar。按常规步骤替换后,程序启动抛出 ClassNotFoundException,但通过压缩工具及命令行验证,缺失的 Class 文件实际存在于新替换的 Jar 包中。
排查过程
1. 初步验证文件存在性
替换操作完成后,首先使用压缩 GUI 工具查看替换后的 jar 包:
观察到 core-service.jar 日期和大小发生变化,说明替换成功。
2. 排除 Jar 包本身问题
为排除新 Jar 包 core-service.jar 本身缺少依赖,在使用 jar xvf app.jar 解压后,直接使用源 Jar 包替换(使用 jar uvf app.jar BOOT-INF/lib/core-service.jar),问题依旧。说明不是新 jar 包本身问题,问题可能存在替换命令上
3. 定位命令行参数问题
对比不同参数的执行效果,发现命令执行完整后会提示压缩比,怀疑是 jar 的二次压缩导致了无法正确找到 class。为了验证猜想,在使用 jar xvf app.jar 解压后,使用 jar uf0 app.jar BOOT-INF/lib/core-service.jar 替换,发现问题被解决,程序正常启动。
问题复盘及操作步骤梳理
1. 操作流程
为避免替换时路径错误,采用完整解压再替换的方案:
- 创建临时目录并进入:
1
mkdir temp && cd temp
- 解压整个外部 Jar 包以保留完整目录结构:
1
jar xvf ../app.jar
- 在临时目录中替换文件:
将新版本core-service.jar复制到temp/BOOT-INF/lib/目录,覆盖旧文件。 - 执行更新命令:按相对路径更新文件,保证 Jar 包内部路径结构正确。
1
jar uf0 ../app.jar BOOT-INF/lib/core-service.jar
- 清理临时文件:
1
cd .. && rm -rf temp
2. 禁用压缩参数的作用
使用 0 参数禁用压缩功能,避免二次压缩导致 Class 文件结构异常:
1 | jar uf0 app.jar BOOT-INF/lib/core-service.jar |
替换完成后,程序启动正常,ClassNotFoundException 问题解决。
原因分析
jar 命令默认使用 DEFLATE 算法压缩文件,在替换内部依赖时,若对已压缩的 Jar 包再次压缩,可能导致 Class 文件结构异常。Spring Boot 的类加载器在扫描 BOOT-INF/lib/ 目录时,无法正确解析异常的 Class 文件,从而抛出 ClassNotFoundException。使用 0 参数禁用压缩后,Class 文件以原始字节码形式存储,类加载器可正常读取。
- 标题: Jar 包替换内部依赖后 ClassNotFoundException 问题排查
- 作者: tsvico
- 创建于 : 2025-11-25 22:32:15
- 更新于 : 2025-11-25 22:32:15
- 链接: https://blog.tbox.fun/2025/2294519147.html
- 版权声明: 本文章采用 CC BY-NC-SA 4.0 进行许可。