1,微信Tinker
framework java Dex分包
客户端下载服务端修复好的dex2包,然后插队在dex前面。客户端再启动,加载。
(替换dex,class)
2,阿里 hotFix,andFix。
今天主要讲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);
第七步,使用jni,C++把两个方法进行替换。