美文网首页
热修复简单版原理实现

热修复简单版原理实现

作者: 马路牙子666 | 来源:发表于2021-04-09 15:59 被阅读0次

    用到生成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 数组
    
        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 数组
    
            Field fieldElement = findField(pathList, DEX_ELEMENTS_FIELD);
            Object[] oldElements = (Object[]) fieldElement.get(pathList);
    
            //4.根据新的dex 文件获取需要插入的dexElements 数组
            //第一个参数
            List<File> dexFiles = new ArrayList<>();
            dexFiles.add(dexFile);
            //第二个参数
            File optimizedDirectory = application.getCacheDir();
            //第三个参数
            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 数组设置给 pathList
            fieldElement.set(pathList, newElements);
        }
    
    
        /**
         * 根据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;
        }
    
        /**
         * 查找对象中对应方法
         *
         * @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;
        }
    
    }
    
    

    相关文章

      网友评论

          本文标题:热修复简单版原理实现

          本文链接:https://www.haomeiwen.com/subject/tftwkltx.html