尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

Spring Boot Jar包修改配置文件和Class中硬编码IP的完整指南

Spring Boot Jar包修改配置文件和Class中硬编码IP的完整指南 前言在实际开发中我们有时会遇到这样的情况从第三方或历史版本中拿到一个 Spring Boot 打好的jar包但里面某个服务的 IP 地址是写死的无论是在application.yml还是直接在 Java 代码中作为字符串常量。由于无法获取源码或重新编译我们需要一种直接修改 jar 包的方法来替换 IP。本文将以一个真实场景为例详细介绍如何不借助源码直接修改 Spring Boot fat jar 中的application.yml配置文件和.class字节码中的硬编码 IP并重新打包成可运行的 jar。问题背景有一个 Spring Boot 项目编译后的collector.jar内部包含BOOT-INF/classes/application.yml—— 配置文件中写死了旧 IP192.168.1.100BOOT-INF/classes/com/xcr/socket/CollectorApplication.class—— 字节码中硬编码了 IPxxx.175.167.44现在需要将这两处 IP 都改为新的10.0.0.5并且保证修改后的 jar 能正常启动。解决思路类型修改方法工具配置文件application.yml文本替换文本编辑器 / PowerShell.class中的硬编码字符串字节码修改替换常量池Javassist为什么不用反编译再重新编译因为反编译后的代码可能不完整且重新编译需要完整的依赖和环境很容易失败。直接操作字节码更安全可靠。环境准备JDK 8本文以 JDK 8 为例下载 Javassisthttps://repo1.maven.org/maven2/org/javassist/javassist/3.29.2-GA/javassist-3.29.2-GA.jar将原 jar 包例如collector.jar和javassist.jar放在同一个工作目录下操作步骤1. 解压 jar 包jar xf collector.jar解压后会出现BOOT-INF和META-INF等目录。BOOT-INF/classes下就是项目的 class 文件和配置文件。2. 修改 application.yml直接用文本编辑器如 VS Code, Notepad打开BOOT-INF/classes/application.yml将其中所有的192.168.1.100替换为10.0.0.5保存。3. 修改 CollectorApplication.class 中的硬编码 IP这里不使用反编译而是直接用Javassist操作字节码。核心原理找到所有ldc指令加载字符串常量检查其指向的常量池条目是否为旧 IP若是则修改常量池索引使其指向新 IP 字符串。新建FixIPBytecode.java完整代码如下import javassist.*; import javassist.bytecode.*; public class FixIPBytecode { public static void main(String[] args) throws Exception { // TODO: 修改为你的旧IP和新IP String oldIp xxx.175.167.44; String newIp 10.0.0.5; ClassPool pool ClassPool.getDefault(); pool.insertClassPath(BOOT-INF/classes/); CtClass ctClass pool.get(com.xcr.socket.CollectorApplication); CtMethod[] methods ctClass.getDeclaredMethods(); for (CtMethod method : methods) { MethodInfo methodInfo method.getMethodInfo(); CodeAttribute codeAttr methodInfo.getCodeAttribute(); if (codeAttr null) continue; CodeIterator iterator codeAttr.iterator(); ConstPool constPool methodInfo.getConstPool(); while (iterator.hasNext()) { int index iterator.next(); int op iterator.byteAt(index); // 0x12 是 ldc 的操作码加载常量 if (op Opcode.LDC) { int constPoolIndex iterator.byteAt(index 1); if (constPool.getTag(constPoolIndex) ConstPool.CONST_String) { String currentStr constPool.getStringInfo(constPoolIndex); if (oldIp.equals(currentStr)) { int newConstPoolIndex constPool.addStringInfo(newIp); iterator.writeByte(newConstPoolIndex 0xff, index 1); System.out.println(在方法 method.getName() 中找到并替换常量: oldIp - newIp); } } } } } ctClass.writeFile(BOOT-INF/classes/); ctClass.detach(); System.out.println(Class 文件修改完成。); } }编译并运行javac -cp .;javassist.jar FixIPBytecode.java java -cp .;javassist.jar FixIPBytecode执行后控制台输出类似在方法 main 中找到并替换常量: xxx.175.167.44 - 10.0.0.5 Class 文件修改完成。此时BOOT-INF/classes/com/xcr/socket/CollectorApplication.class已被修改。4. 将修改后的文件更新回 jar 包注意不要重新打包整个 jar即不要用jar cf那样会破坏 Spring Boot 的启动信息。而是用jar uf只替换修改过的文件jar uf collector.jar BOOT-INF/classes/application.yml jar uf collector.jar BOOT-INF/classes/com/xcr/socket/CollectorApplication.class5. 清理临时目录并测试# 删除解压出的目录 rmdir /s /q BOOT-INF META-INF org # 运行修改后的 jar java -jar collector.jar观察日志确认新 IP 已生效。一键脚本Windows .bat为了方便可以将上述步骤整合成一个批处理脚本fix_ip.batecho off echo 1. 解压JAR... jar xf collector.jar echo 2. 修改application.yml... powershell -Command (Get-Content BOOT-INF\classes\application.yml) -replace 192.168.1.100, 10.0.0.5 | Set-Content BOOT-INF\classes\application.yml echo 3. 编译并运行Javassist修改class... javac -cp .;javassist.jar FixIPBytecode.java java -cp .;javassist.jar FixIPBytecode echo 4. 更新JAR包... jar uf collector.jar BOOT-INF/classes/application.yml jar uf collector.jar BOOT-INF/classes/com/xcr/socket/CollectorApplication.class echo 5. 清理临时目录... rmdir /s /q BOOT-INF META-INF org 2nul echo 完成新jar已生成collector.jar pause将FixIPBytecode.java和javassist.jar放在同一目录双击运行fix_ip.bat即可。常见问题与排错Q1: 运行javac时提示“找不到符号 ExprEditor / StringConst”这是因为之前网上有些教程使用了错误的类名。本文提供的FixIPBytecode.java直接操作常量池和字节码不依赖那些不存在的类可以避免此问题。Q2: 运行java时提示“ClassNotFoundException: javassist.ClassPool”请检查 classpath 是否包含javassist.jar且写法正确Windows 用分号分隔当前目录用.表示。正确命令bashjava -cp .;javassist.jar FixIPBytecodeQ3: Javassist 没有找到要替换的 IP 字符串先用javap确认 class 文件中确实存在该字符串bashjavap -v BOOT-INF/classes/com/xcr/socket/CollectorApplication.class | findstr xxx.175.167.44如果能看到类似#7 String ...的输出说明字符串存在于常量池。我们的脚本通过遍历所有ldc指令来匹配通常都能找到。Q4: 修改后 jar 无法启动提示“找不到主类”一定不要使用jar cf重新打包整个目录。必须使用jar uf只替换个别文件才能保留原 jar 中的META-INF/MANIFEST.MF和 Spring Boot 的启动类索引。Q5: PowerShell 替换 YAML 时格式错乱简单替换偶尔会改变文件编码或换行符。如果担心可以手动编辑application.yml或用专业文本编辑器替换。脚本中的 PowerShell 命令对于普通字符串替换是安全的。总结通过本文的方法你可以无需源码、无需反编译直接修改 Spring Boot fat jar 中的配置文件和字节码中的硬编码字符串。核心思路是用jar xf解压。直接编辑文本配置文件。使用 Javassist 操作字节码常量池替换ldc指令的目标字符串。用jar uf增量更新回原 jar。该方法适用于修改 IP 地址、数据库连接字符串、密钥等任何硬编码在 Java 代码中的字符串常量。希望这篇教程能帮你解决实际问题。如果你有其他修改场景比如修改数字常量、修改方法调用等也可以在评论区留言交流。本文配套资源下载Javassist jarhttps://repo1.maven.org/maven2/org/javassist/javassist/3.29.2-GA/javassist-3.29.2-GA.jar完整脚本和源码见文中代码块
返回列表