android中的jar包反编译修改心得小结

时间:2024-03-03 21:20:20

最近修改了某个android的第三方jar包里的代码,在此记录一下心得

一开始想用jd-gui转成.java文件,修改后再重新编译回class,然后放进jar中覆盖掉原来的class文件。然而在编译回去时发现因为代码引用了部分android的类,用java命令等方式无法编译回class文件。于是我尝试通过直接修改class文件来实现修改代码。

  1. 找到jar包中对应的class文件的路径
  2. 建一个可以直接执行的java类
  3. 调用javassist.jar的API来写代码实现修改对应代码(示例代码在底下,关于javassist.jar的API请自行百度)
  4. 执行修改class文件的代码
  5. 生成的已修改class位于项目根目录下对应的class文件路径下(例:com.a.bb.A.class, 程序执行后class文件会生成在: 当前项目/com/a/bb/A.class
  6. 覆盖掉出来的class文件夹中原先的class文件
  7. 使用cmd命令:jar cvf test.jar命令重新打包
  8. 然后在项目中测试一下修改后的jar就大功告成了!

很烦躁的是前几天整理硬盘时候没注意把平常java测试用项目删掉了,只能贴出聊天记录中的部分代码

    public static void main(String[] args) {
        
        ClassPool pool = ClassPool.getDefault();
        try {
            //取得需要反编译的jar文件,设定路径
            pool.insertClassPath("G://abc//XXSDK_Android.jar");
            
            //取得需要反编译修改的文件,注意是完整路径(注意:因为代码在内部类中,所以我读取的是WebViewActivity$2文件
//            CtClass cc1 = pool.get("com.objectplanet.chart.a");
            CtClass cc1 = pool.get("com.xx.webview.WebViewActivity$2");
            
            //取得需要修改的方法
            CtMethod method = cc1.getDeclaredMethod("shouldUrlLoading");
            
            //插入修改项,我们让他直接返回(注意:根据方法的具体返回值返回,因为这个方法返回值是void,所以直接return;)
            method.instrument(
                    new ExprEditor() {
                        public void edit(MethodCall m)
                                throws CannotCompileException {

                            System.out.println(m.getClassName() + ", " + m.getMethodName());
                            // 在这里搜索class中符合条件的逻辑代码,并替换成我想改的
                            if ( m.getClassName().equals("java.lang.String")
                                    && m.getMethodName().equals("startsWith")) {
                                m.replace(
                                        "$_ = $proceed(\"http\") ;");
                            }
                        }
                    });

            //写入保存
            cc1.writeFile();
        } catch (NotFoundException e) {
            e.printStackTrace();
        } catch (CannotCompileException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }

    }

PS:

  1. 如果发现修改不了对应的代码,那是因为对应的代码不是在那个A.class文件中。(没错,你没听错) 举例来说:我想修改匿名内部类中的代码,需要修改的class文件是
    A$.class系列,而不是A.class本身,因为编译成class文件后,内部类的代码实际上是放在A$.class文件中的
  2. 把class文件直接丢进jar包中有可能会导致用不了,这时候用命令重新打包试试
  3. 按住Shift+右键,在右键菜单中会出现“在此处打开命令窗口(W)”的选项

如果只是要修改某个字符串,可以使用JBE(Java Bytecode Editor)。 JBE是一个Java字节码编辑工具,可以查看和编辑该方法的字节码, 字节码化的代码虽然不容易看懂. 但是字符串内容不会变. 所以很适用于只需要修改某个字符串(比如正则)内容的需求. 找到对应方法的字节码,点击Code Editor找到对应字符串直接编辑完点保存就能拿到一个修改好的class文件.
JBE使用教程
JBE下载地址