android用 javassist實現捕獲第三方庫異常


Git傳送門

Android開發中不可避免的會用到很多第三方庫, 如果碰到異常 常常有種心有余而力不足的想法,如果是開源的 你可以吧源碼導入進來進行修改,但不可避免的會造成維護性差, 本文提供一個捕獲屏蔽第三方庫異常的思路,也可以擴展為在編譯時修改第三方庫代碼,從而插入自己的需求

1.Javassist 簡介

  javassist是一個修改java字節碼的開源庫

 下面是個很簡單的例子,獲取一個classPool,設置運行所需要的庫,寫入到對應位置

 具體語法可以參考 Javassist介紹

ClassPool pool = ClassPool.getDefault();
pool.insertClassPath("/usr/local/javalib");
CtClass cc = pool.get("test.Rectangle");
cc.setSuperclass(pool.get("test.Point"));
cc.writeFile();

 2.在安卓中的應用

 gradle 編譯安卓項目是通過一個個task來執行任務, 我們可以通過gradle看到很多transform*的task

 在編譯時插入一個自己的transform 從而實現對源碼或第三方jar庫攔截 實現修改第三方庫

下面時定義一個gradle插件, 注冊一個自己的transform

public class MainPlugin implements Plugin<Project>{
    void apply(Project project) {
        project.logger.error("Dhjar start=========================")
        project.extensions.create("dhjar", LJarConfig)
        project.android.registerTransform(new JavassistTransform(project))
    }
}

transform的幾個方法 

//獲取輸入類型jar或者class  
@Override
public Set<QualifiedContent.ContentType> getInputTypes() { return TransformManager.CONTENT_CLASS; } //需要處理的范圍, 主項目 子項目 或者三方庫 @Override public Set<? super QualifiedContent.Scope> getScopes() { Set<QualifiedContent.Scope> sets = new HashSet<QualifiedContent.Scope>() sets.add(QualifiedContent.Scope.EXTERNAL_LIBRARIES) return sets; } @Override Set<? super QualifiedContent.Scope> getReferencedScopes() { Set<QualifiedContent.Scope> sets = new HashSet<QualifiedContent.Scope>() sets.add(QualifiedContent.Scope.EXTERNAL_LIBRARIES) sets.add(QualifiedContent.Scope.PROVIDED_ONLY) return sets }

 

他的核心方法就是  分別為獲取jar 和source目錄

    @Override
    public void transform(TransformInvocation transformInvocation) throws IOException {
}

下面就是捕獲第三方異常的核心代碼 通過插入一個相同的方法包裹上try catch 從而攔截需要捕獲的方法, 具體代碼可以看開頭的鏈接
    private static void modify(CtClass c, ClassPool mClassPool,List<String> methods) {
        if (c.isFrozen()) {
            c.defrost()
        }
        System.out.println("find class==============="+c.getName())
        for(String method : methods){
            CtMethod ctMethod = c.getDeclaredMethod(method)
            String method2 = method+"DhCut"
            CtMethod ctMethod2 = CtNewMethod.copy(ctMethod,method2,c,null)
            c.addMethod(ctMethod2)
            int methodLen = ctMethod.getParameterTypes().length
            StringBuffer sb  = new StringBuffer()
            sb.append("{try{")
            if(!ctMethod.getReturnType().getName().contains("void")){
                sb.append("return ")
            }
            sb.append(method2)
            sb.append("(")
            for(int i = 0; i<methodLen;i++){
                sb.append("\$"+(i+1))
                if(i!=methodLen-1){
                    sb.append(",")
                }
            }
            sb.append(");}catch(Exception ex){ System.out.println(ex.toString());ex.printStackTrace();}")
            if(!ctMethod.getReturnType().getName().contains("void")){
                sb.append("return ")
                String result = getReturnValue(ctMethod.getReturnType().getName())
                sb.append(result)
                sb.append(";")
            }
            sb.append("}")
           System.out.println("return type  =======" +ctMethod.getReturnType().getName())
            ctMethod.setBody(sb.toString())
        }
    }

 

 攔截前得類 此時我們直接調用getString 或造成空指針崩潰
package com.vova.testlibrary;

public class TestFile
{
  public int getInt()
  {
    return 1;
  }
  
  public float getFloat()
  {
    return 0.0F;
  }
  
  public double getDoulbe()
  {
    return 0.0D;
  }
  
  public long getLong()
  {
    return 0L;
  }
  
  public char getChar()
  {
    return 'a';
  }
  
  public short getShort()
  {
    return 0;
  }
  
  public double getDouble()
  {
    return 0.0D;
  }
  
  public String getString()
  {
    String aa = null;
    int len = aa.length();
    return null;
  }
  
  public byte getByte()
  {
    return 0;
  }
}
View Code

 

   gradle編譯效果圖   輸入test.jar   輸出19.jar  打印需要替換的方法

下面是19.jar源碼
package com.vova.testlibrary;

import java.io.PrintStream;

public class TestFile
{
  public int getIntDhCut()
  {
    return 1;
  }
  
  public float getFloatDhCut()
  {
    return 0.0F;
  }
  
  public double getDoulbe()
  {
    return 0.0D;
  }
  
  public long getLongDhCut()
  {
    return 0L;
  }
  
  public char getCharDhCut()
  {
    return 'a';
  }
  
  public short getShortDhCut()
  {
    return 0;
  }
  
  public double getDoubleDhCut()
  {
    return 0.0D;
  }
  
  public String getStringDhCut()
  {
    String aa = null;
    int len = aa.length();
    return null;
  }
  
  public byte getByteDhCut()
  {
    return 0;
  }
  
  public int getInt()
  {
    try
    {
      return getIntDhCut();
    }
    catch (Exception localException)
    {
      System.out.println(localException.toString());
      localException.printStackTrace();
    }
    return 0;
  }
  
  public float getFloat()
  {
    try
    {
      return getFloatDhCut();
    }
    catch (Exception localException)
    {
      System.out.println(localException.toString());
      localException.printStackTrace();
    }
    return 0.0F;
  }
  
  public long getLong()
  {
    try
    {
      return getLongDhCut();
    }
    catch (Exception localException)
    {
      System.out.println(localException.toString());
      localException.printStackTrace();
    }
    return 0L;
  }
  
  public char getChar()
  {
    try
    {
      return getCharDhCut();
    }
    catch (Exception localException)
    {
      System.out.println(localException.toString());
      localException.printStackTrace();
    }
    return 'a';
  }
  
  public short getShort()
  {
    try
    {
      return getShortDhCut();
    }
    catch (Exception localException)
    {
      System.out.println(localException.toString());
      localException.printStackTrace();
    }
    return 0;
  }
  
  public double getDouble()
  {
    try
    {
      return getDoubleDhCut();
    }
    catch (Exception localException)
    {
      System.out.println(localException.toString());
      localException.printStackTrace();
    }
    return 0.0D;
  }
  
  public String getString()
  {
    try
    {
      return getStringDhCut();
    }
    catch (Exception localException)
    {
      System.out.println(localException.toString());
      localException.printStackTrace();
    }
    return null;
  }
  
  public byte getByte()
  {
    try
    {
      return getByteDhCut();
    }
    catch (Exception localException)
    {
      System.out.println(localException.toString());
      localException.printStackTrace();
    }
    return 0;
  }
}
View Code

 

 


免責聲明!

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



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