问题背景
在维护 Spring Boot 项目时,经常会遇到一种场景:需要修改可执行 JAR 包内部的某个依赖 JAR(也就是"大包里套小包"的结构),比如修改 BOOT-INF/lib/lx-example-xxx.jar 中的某个 class 文件或配置文件。
很多人第一反应是用 7-Zip、WinRAR 等压缩软件直接打开 JAR 包拖进去替换。但这样操作后,启动程序往往会报出类似下面的错误:
java
java.lang.IllegalStateException: Failed to get nested archive for entry BOOT-INF/lib/lx-example-xxx.jar
It has been compressed and nested jar files must be stored without compression.
根本原因在于:Spring Boot 的可执行 JAR(Fat JAR)内部嵌套的依赖 JAR 必须以"存储模式(STORED)"保存,即不压缩,否则 Spring Boot Loader 无法通过文件偏移量正确读取嵌套 JAR。
为什么普通方法会失败?
失败通常有以下几种原因:
-
- 用压缩软件直接替换:WinRAR、7-Zip 等工具默认会压缩文件,导致嵌套 JAR 变成压缩状态。
-
- 在大包解压目录里直接打包小包 :如果在大包解压后的文件夹里执行小包的
jar -cfM0命令,会把大包的META-INF等目录结构搞乱,导致最终打包结果损坏。
- 在大包解压目录里直接打包小包 :如果在大包解压后的文件夹里执行小包的
-
- 打包命令缺少 -0****参数 :
-0表示不压缩,这是 Spring Boot 嵌套 JAR 的关键要求。
- 打包命令缺少 -0****参数 :
解决方案:大包小包隔离打包法
最稳妥的做法是将大包和小包放在两个完全独立的文件夹里操作,互不干扰,各自打包后再合并。
准备工作
- 1、在桌面新建两个文件夹:
big(放主包)和small(放依赖包)。 - 2、备份原始的
lx-admin-3.3.1.195-RELEASE.jar,避免操作失误无法恢复。 - 、确保电脑已安装 JDK,且
jar命令可在命令行中正常使用。
第一步:解压大包
-
将
lx-admin-3.3.1.195-RELEASE.jar复制到big文件夹。 -
在
big文件夹空白处按住Shift+ 右键,选择"在此处打开 Powershell 窗口"。 -
执行解压命令:
java
jar -xvf lx-admin-3.3.1.195-RELEASE.jar
解压后,big 文件夹里会出现 BOOT-INF、META-INF、org 等目录。
第二步:单独处理小包
-
进入
big/BOOT-INF/lib/目录,找到需要修改的lx-example-3.3.1.195-RELEASE.jar,将其复制到small文件夹。 -
在
small文件夹空白处按住Shift+ 右键,打开 Powershell 窗口。 -
执行解压命令:
jar -xvf lx-example-3.3.1.195-RELEASE.jar
-
解压后,在
small文件夹中找到需要修改的文件(如 class 文件或配置文件),进行修改并保存。 -
修改完成后,在
small窗口的命令行中执行打包命令(注意最后有一个英文句号 .****,表示当前目录):jar -cfM0 lx-example-3.3.1.195-RELEASE.jar .
此时 small 文件夹中会生成一个名为 lx-example-3.3.1.195-RELEASE.jar 的新文件,它已经是"不压缩"模式,可以直接被 Spring Boot 识别。
第三步:替换大包中的小包
-
回到
big文件夹,进入BOOT-INF/lib/目录。 -
删除旧的
lx-example-3.3.1.195-RELEASE.jar。 -
将
small文件夹中新生成的lx-example-3.3.1.195-RELEASE.jar复制进来。
第四步:重新打包大包
-
回到
big文件夹的最外层(能看到BOOT-INF、META-INF、org三个目录的地方)。 -
在空白处按住
Shift+ 右键,打开 Powershell 窗口。 -
执行最终打包命令:
jar -cfM0 lx-admin-3.3.1.195-RELEASE.jar BOOT-INF META-INF org
打包完成后,big 文件夹中会生成最终的 lx-admin-3.3.1.195-RELEASE.jar。
第五步:验证
将生成的 JAR 包上传到服务器,执行:
java -jar lx-admin-3.3.1.195-RELEASE.jar
如果程序正常启动,说明修改成功。
关键注意事项
● -0****参数不可省略:这是"不压缩"的关键标识,数字零,不是字母 O。
● 大包和小包必须在不同文件夹操作:避免目录结构互相污染。
● 不要删除 META-INF**、** org****目录 :META-INF/MANIFEST.MF 包含启动类配置,org 目录包含 Spring Boot Loader。
● 签名文件处理 :如果原 JAR 包包含 META-INF/*.SF、*.RSA 等签名文件,修改后签名会失效,测试环境可删除这些文件。
● 始终保留原始 JAR 包备份:防止操作失误导致无法回退。
总结
修改 Spring Boot 嵌套 JAR 的核心要点只有两个:大包小包隔离操作 ,以及全程使用 -0****不压缩模式打包。只要严格遵循这两点,就能避免绝大多数打包失败的问题。