一、需求:
第三方jar包中的代码不符合项目的需求,需要对某个class文件进行修改,从而满足项目的需求。通常采用对class文件进行反编译,然后在重新生成jar包。但是反编译的结果不能100%正确,所以直接对class文件进行修改更为直接、可靠。
二、安装jclasslib Bytecode Viewer插件
IEDA: File\Settings\Plugins,在MarketPlace中搜索jclasslib Bytecode Viewer插件,重启IDEA使插件生效
三、准备要修改的class文件
1、IDEA对jar包中的代码进行调试,通过断点确定需要修改的类,该类中的属性或函数。如:GenericHibernateDao类 sendHistoryMessageToRedis方法中的某个字段需要修改。
2、在IDEA中选择该class文件,选择View\Show Bytecode With Jclasslib打开jclassLib插件对话框3、在方法中找到sendHistoryMessageToRedis,选择code找到该字符串对应的ID:45
4、点击ID45,跳转到常量池,获取字符串对应的行号:418
四、修改Class文件
1、IDEA中新建工程,创建ModifyClassFilesTest.java文件。该文件需要修改3个地方:
①、filePath为class文件的路径;
②、修改行号;
③、修改要写入的内容为:"Reids’s Key: "。
import java.io.*;import org.gjt.jclasslib.io.ClassFileWriter;
import org.gjt.jclasslib.structures.ClassFile;
import org.gjt.jclasslib.structures.Constant;
import org.gjt.jclasslib.structures.constants.ConstantUtf8Info;public class ModifyClassFilesTest {public static void main(String[] args) throws Exception {String filePath = "E:\\common\\dao\\impl\\GenericHibernateDao.class";FileInputStream fis = new FileInputStream(filePath);DataInput di = new DataInputStream(fis);ClassFile cf = new ClassFile();cf.read(di);Constant[] infos = cf.getConstantPool();int count = infos.length;for (int i = 0; i < count; i++) {if (infos[i] != null) {if(i==165){\\Class文件中对应的行号System.out.print(i);System.out.print(" = ");System.out.print(infos[i].getVerbose());System.out.print(" = ");System.out.println(infos[i]);System.out.println(infos[i].getClass().getSimpleName());ConstantUtf8Info uInfo = (ConstantUtf8Info)infos[i];//根据对应的类型转换uInfo.setString("Reids's Key: ");//设置对应内容infos[i]=uInfo;}}}cf.setConstantPool(infos);fis.close();File f = new File(filePath);ClassFileWriter.writeToFile(f, cf);}
}
2、导入依赖,已经在IEDA中安装了jclasslib的插件,所以相关jar包的路径为:C:\Users\用户.IntelliJIdea2019.3\config\plugins\jclasslib\lib,将该路径下的jar包都导入到工程中。
3、运行ModifyClassFilesTest,执行后jar包中的class文件已经被修改
五、注意
1、修改前对jar包和class文件进行备份
2、该方式只适用于修改字符串(我认为)