android中的jar包反編譯修改心得小結


最近修改了某個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下載地址


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM