热修复Dex替换

热修复

两种loader  load不同的dex

首先需要将修复的class打包成dex(需要用dex工具)

SystemClassLoader:dexElements(classes1.dex,classes2.dex.......)

DexClassesLoader:dexElements(fixclasses.dex,)

然后利用反射拿到SystemClassLoader.pathList这个字段,然后再拿到dexElemens,和DexClassLoader中的Dex数组进行合并,最后再setField回SystemClassLoader中

方法类

public class HookHelper {

    public static Object getField(Object object, Class c1, String field) {

        try {

            Field localField = c1.getDeclaredField(field);

            localField.setAccessible(true);

            return localField.get(object);

        } catch (Exception e) {

            e.printStackTrace();

        }

        return null;

    }

    public static void setField(Object object, Object value) {

        try {

            Field localField = object.getClass().getDeclaredField(value.getClass().getName());

            localField.setAccessible(true);

            localField.set(object, value);

        } catch (Exception e) {

            e.printStackTrace();

        }

    }

}

使用

public class HotFix {

    private static final String BASE_DEX_CLASS_LOADER = "dalvik.system.BaseDexClassLoader";

    private static final String PATH_LIST = "pathList";

    private static final String DEX_PATH_LIST = "dalvik.system.DexPathList";

    private static final String ELEMENT_LIST = "dexElements";

    //Dex插桩

    private static void doDexInject(Context context, File fileDir, HashSet loadedDEx) {

        String optimizeDir = fileDir.getAbsolutePath() + File.separator + "opt_dex";

        File fopt = new File(optimizeDir);

        if (!fopt.exists()) {

            fopt.mkdirs();

        }

        PathClassLoader pathClassLoader = (PathClassLoader) context.getClassLoader();

        for (File file : loadedDEx) {

            DexClassLoader classLoader = new DexClassLoader(file.getAbsolutePath(), optimizeDir, null, pathClassLoader);

            //拿到ClassLoader-->PathList-->Elements

            try {

                //获取PathList

                Object dexObj = HookHelper.getField(classLoader, Class.forName(BASE_DEX_CLASS_LOADER), PATH_LIST);

                Object pathObj = HookHelper.getField(pathClassLoader, Class.forName(BASE_DEX_CLASS_LOADER), PATH_LIST);

                //获取elements

                Object dexDexElementList = HookHelper.getField(dexObj, Class.forName(DEX_PATH_LIST), ELEMENT_LIST);

                Object pathDexElementList = HookHelper.getField(pathObj, Class.forName(DEX_PATH_LIST), ELEMENT_LIST);

                //合并

                Object allElements = combineArray(dexDexElementList, pathDexElementList);

                //设置回去

                HookHelper.setField(pathObj, allElements);

            } catch (ClassNotFoundException e) {

                e.printStackTrace();

            }

        }

    }

    //合并Element,修复包在前

    private static Object combineArray(Object arrayLhs, Object arrayRhs) {

        Class localClass = arrayLhs.getClass().getComponentType();

        int i = Array.getLength(arrayLhs);

        int j = i + Array.getLength(arrayRhs);

        Object result = Array.newInstance(localClass, j);

        for (int k = 0; k < j; ++k) {

            if (k < i) {

                Array.set(result, k, Array.get(arrayLhs, k)); //修复包

            } else {

                Array.set(result, k, Array.get(arrayRhs, k - i)); //宿主

            }

        }

        return result;

    }

}

你可能感兴趣的:(热修复Dex替换)