Android热修复原理

来源:互联网 发布:通利琴行淘宝店铺 编辑:程序博客网 时间:2024/05/19 13:20

1,微信Tinker  

framework  java  Dex分包  

 

客户端下载服务端修复好的dex2包,然后插队在dex前面。客户端再启动,加载。

(替换dexclass

 

2,阿里 hotFixandFix

今天主要讲AndFix原理。

第一步,确定异常的类,以及该类的方法。

第二步,进行bug修复,并且在这个类里面进行注解反射,绑定需要修复的类和方法。
注解:
package andfix.shenbin.com.ali_andfix_hotfix.fix;import java.lang.annotation.ElementType;import java.lang.annotation.Retention;import java.lang.annotation.RetentionPolicy;import java.lang.annotation.Target;/** * 通过注解的方式 * Created by Administrator on 2017/9/8. */@Target(ElementType.METHOD)@Retention(RetentionPolicy.RUNTIME)public @interface Replace {    String clazz();    String method();}

原发生错误的类和方法:
package andfix.shenbin.com.ali_andfix_hotfix.client;/** * Created by Administrator on 2017/9/8. */public class TestClass {    public int getResult(){        int i = 0;        int j = 10 ;        return  j/i;  //会抛异常    }}

修复之后的方法和方法:
package andfix.shenbin.com.ali_andfix_hotfix.service;import andfix.shenbin.com.ali_andfix_hotfix.fix.Replace;/** * 服务的修复好的class,编译之后,在build里面生成 * 路径:build/intermediates/classes/debug/包名/service/TestClass.class * 2,然后找到 D:\android\AS\sdk\build-tools\22.0.1 dx.bat  ,把这个配置成环境变量 * 3,执行命令,打dex包。dx --dex --output=输出的dex文件的路径和文件名(文件名自己指定) 编译好的class的路径 * * Created by Administrator on 2017/9/8. */public class TestClass {    //指定要修复的类和方法名    @Replace(clazz = "andfix.shenbin.com.ali_andfix_hotfix.client.TestClass",method = "getResult");    public int getResult(){        int i = 1;        int j = 10 ;        return  j/i;    }}

第三步,编译,并且把编译生成的class利用sdk里面的dx.bat 工具进行dex打包。

第四步,把修复好,生成好的dex包上传到服务器,让用户下载。


第五步,app客户端加载dex包。

/** * @param sourcePathName 已经下载好在sd卡上的修复了的dex文件 * @param outputPathName * @param flags */public void loadDexFile(String sourcePathName,String outputPathName,int flags){    DexFile dexFile = null;    try {        dexFile = DexFile.loadDex(sourcePathName, outputPathName, flags);        Enumeration<String> entry = dexFile.entries();        while (entry.hasMoreElements()){            String className = entry.nextElement();            Class realClazz = dexFile.loadClass(className,context.getClassLoader());            fix(realClazz);        }    } catch (IOException e) {        e.printStackTrace();    }}/** * 修复 * @param realClazz */public void fix(Class realClazz){    Method[] methods = realClazz.getDeclaredMethods();    for (Method method : methods) {        Replace replace = method.getAnnotation(Replace.class);        if(replace == null){            continue;        }        String wrongClassName = replace.clazz();        String wrongMethodName = replace.method();        try {            Class wrongClass = Class.forName(wrongClassName);            //最终拿到错误的method            Method wrongMethod = wrongClass.getMethod(wrongMethodName,method.getParameterTypes());            //修复,nativi的方法,需要用jni编程,进行两个方法的替换。            replace(wrongMethod,method);        } catch (ClassNotFoundException e) {            e.printStackTrace();        } catch (NoSuchMethodException e) {            e.printStackTrace();        }    }}
第六步,找到修复好的class,找到Method(修复好的),找到Method(有bug的)。//用c++ 去进行两个方法替换。java做不到。private native void replace(Method wrongMethod,Method method);

 

第七步,使用jniC++把两个方法进行替换。