Jar 包替换内部依赖后 ClassNotFoundException 问题排查

Jar 包替换内部依赖后 ClassNotFoundException 问题排查

tsvico Lv5

问题描述

在维护 Spring Boot 项目时,需更新外部 Jar 包 app.jarBOOT-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. 创建临时目录并进入:
    1
    mkdir temp && cd temp
  2. 解压整个外部 Jar 包以保留完整目录结构:
    1
    jar xvf ../app.jar
  3. 在临时目录中替换文件:
    将新版本 core-service.jar 复制到 temp/BOOT-INF/lib/ 目录,覆盖旧文件。
  4. 执行更新命令:
    1
    jar uf0 ../app.jar BOOT-INF/lib/core-service.jar
    按相对路径更新文件,保证 Jar 包内部路径结构正确。
  5. 清理临时文件:
    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 进行许可。
评论