熱修復(fù)簡單版原理實現(xiàn)

用到生成dex命令
dx --dex --output = xx.dex com\xxxx\xxx\xxx.class

public class HotFixUtil {

    private final static String PATH_LIST_FIELD = "pathList";//pathList 屬性
    private final static String DEX_ELEMENTS_FIELD = "dexElements";//dexElements 屬性
    /**
     * makeDexElements(List<File> files, File optimizedDirectory,
     * List<IOException> suppressedExceptions, ClassLoader loader)
     */
    private final static String MAKE_DEX_ELEMENTS = "makeDexElements";//將dex 變成 elements 數(shù)組

    public static void install(Application application, File dexFile) throws IllegalAccessException, InvocationTargetException {
        //1.獲取 當前項目類加載器
        ClassLoader classLoader = application.getClassLoader();
        //2.獲取類加載器中的 pathList
        Field pathListField = findField(classLoader, PATH_LIST_FIELD);
        Object pathList = pathListField.get(classLoader);
        //3.獲取舊的 dexElements 數(shù)組

        Field fieldElement = findField(pathList, DEX_ELEMENTS_FIELD);
        Object[] oldElements = (Object[]) fieldElement.get(pathList);

        //4.根據(jù)新的dex 文件獲取需要插入的dexElements 數(shù)組
        //第一個參數(shù)
        List<File> dexFiles = new ArrayList<>();
        dexFiles.add(dexFile);
        //第二個參數(shù)
        File optimizedDirectory = application.getCacheDir();
        //第三個參數(shù)
        List<IOException> suppressedExceptions = new ArrayList();
        Method method = findMethod(pathList, MAKE_DEX_ELEMENTS, List.class, File.class, List.class, ClassLoader.class);
        Object[] dexElements = (Object[]) method.invoke(pathList, dexFiles, optimizedDirectory, suppressedExceptions, classLoader);

        //5.將兩個dexElements 合并成一個新的
        Class<?> componentType = dexElements.getClass().getComponentType();
        Object[] newElements = (Object[]) Array.newInstance(componentType, oldElements.length + dexElements.length);
        System.arraycopy(dexElements, 0, newElements, 0, dexElements.length);
        System.arraycopy(oldElements, 0, newElements, dexElements.length, oldElements.length);
        //6.將新的dexElements 數(shù)組設(shè)置給 pathList
        fieldElement.set(pathList, newElements);
    }


    /**
     * 根據(jù)name 查詢對象中屬性
     * 如果當前類沒有 就去父類找
     *
     * @param instance
     * @param fieldName
     * @return
     */
    private static Field findField(Object instance, String fieldName) {
        Class<?> aClass = instance.getClass();
        while (aClass != null) {
            try {
                Field field = aClass.getDeclaredField(fieldName);
                if (!field.isAccessible()) {
                    field.setAccessible(true);
                }
                return field;
            } catch (NoSuchFieldException e) {
                e.printStackTrace();
            }
            aClass = aClass.getSuperclass();
        }
        return null;
    }

    /**
     * 查找對象中對應(yīng)方法
     *
     * @param instance
     * @param methodName
     * @return
     */
    private static Method findMethod(Object instance, String methodName, Class<?>... args) {
        Class<?> aClass = instance.getClass();
        while (aClass != null) {
            try {
                Method method = aClass.getDeclaredMethod(methodName, args);
                if (!method.isAccessible()) {
                    method.setAccessible(true);
                }
                return method;
            } catch (NoSuchMethodException e) {
                e.printStackTrace();
            }
            aClass = aClass.getSuperclass();
        }
        return null;
    }

}

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容