记录:替换线上springboot项目可执行jar包中依赖jar里的class文件
问题背景:
项目组发现线上版本问题后,定位是由于项目依赖的某个jar包中有个小BUG。
解决方案:
在修改了对应的java文件后,编译出对应的class文件。从生产环境下载项目jar包,解压后,找到对应的依赖jar包,使用好压软件打开,用修改后的class文件覆盖原来的文件。
然后使用jar -cf0M XXX.jar -C imp . 命令将之前解压的文件夹重新打包成可执行jar包。有关jar命令参数可以参考下面(最后的“.”表示打包imp文件夹中所有文件):
用法: jar {ctxui}[vfmn0PMe] [jar-file] [manifest-file] [entry-point] [-C dir] files ... 选项: -c 创建新档案 -t 列出档案目录 -x 从档案中提取指定的 (或所有) 文件 -u 更新现有档案 -v 在标准输出中生成详细输出 -f 指定档案文件名 -m 包含指定清单文件中的清单信息 -n 创建新档案后执行 Pack200 规范化 -e 为捆绑到可执行 jar 文件的独立应用程序 指定应用程序入口点 -0 仅存储; 不使用任何 ZIP 压缩 -P 保留文件名中的前导 '/' (绝对路径) 和 ".." (父目录) 组件 -M 不创建条目的清单文件 -i 为指定的 jar 文件生成索引信息 -C 更改为指定的目录并包含以下文件 如果任何文件为目录, 则对其进行递归处理。 清单文件名, 档案文件名和入口点名称的指定顺序 与 'm', 'f' 和 'e' 标记的指定顺序相同。 示例 1: 将两个类文件归档到一个名为 classes.jar 的档案中: jar cvf classes.jar Foo.class Bar.class 示例 2: 使用现有的清单文件 'mymanifest' 并 将 foo/ 目录中的所有文件归档到 'classes.jar' 中: jar cvfm classes.jar mymanifest -C foo/ .
注意:不能直接将新的依赖jar包通过好压替换到项目jar包中,运行jar包时会出现如下错误信息:
Exception in thread "main" java.lang.IllegalStateException: Failed to get nested archive for entry BOOT-INF/lib/icity-core-2.1.0.jar at org.springframework.boot.loader.archive.JarFileArchive.getNestedArchive(JarFileArchive.java:113) at org.springframework.boot.loader.archive.JarFileArchive.getNestedArchives(JarFileArchive.java:87) at org.springframework.boot.loader.ExecutableArchiveLauncher.getClassPathArchives(ExecutableArchiveLauncher.java:69) at org.springframework.boot.loader.Launcher.launch(Launcher.java:50) at org.springframework.boot.loader.JarLauncher.main(JarLauncher.java:52) Caused by: java.io.IOException: Unable to open nested jar file 'BOOT-INF/lib/icity-core-2.1.0.jar' at org.springframework.boot.loader.jar.JarFile.getNestedJarFile(JarFile.java:261) at org.springframework.boot.loader.jar.JarFile.getNestedJarFile(JarFile.java:247) at org.springframework.boot.loader.archive.JarFileArchive.getNestedArchive(JarFileArchive.java:109) ... 4 more Caused by: java.lang.IllegalStateException: Unable to open nested entry 'BOOT-INF/lib/icity-core-2.1.0.jar'. It has been compressed and nested jar files must be stored without compression. Please check the mechanism used to create your executable jar file at org.springframework.boot.loader.jar.JarFile.createJarFileFromFileEntry(JarFile.java:287) at org.springframework.boot.loader.jar.JarFile.createJarFileFromEntry(JarFile.java:269) at org.springframework.boot.loader.jar.JarFile.getNestedJarFile(JarFile.java:258) ... 6 more
这个错误的意思是无法打开其中依赖的jar包,因为它被压缩了。所以我才用jar命令其中的参数-0表示仅存储,不做任何zip压缩。