Android热修复原理

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++把两个方法进行替换。

Android热修复原理

Android热修复原理