ART双亲委托机制杂记

1.ART双亲委托机制:
    PathClassLoader,DexClassLoader --继承自--> BaseDexClassLoader  --继承自--> ClasssLoader

     protected Class loadClass(String name, boolean resolve)
            throws ClassNotFoundException
        {
                // First, check if the class has already been loaded
                Class c = findLoadedClass(name); //首次由本身自己去查询是否加载过
                if (c == null) {
                    try {
                        if (parent != null) {
                            c = parent.loadClass(name, false); //由父类去加载
                        } else {
                            //若顶级类加载器父类是空 则调用这个方法 这个方法是又ClassLoader类提供的private方法,默认返回null
                            c = findBootstrapClassOrNull(name); 
                        }
                    } catch (ClassNotFoundException e) {
                        // ClassNotFoundException thrown if class not found
                        // from the non-null parent class loader
                    }

                    if (c == null) { //如果父类加载器都加载为空  那么由本身去加载
                        // If still not found, then invoke findClass in order
                        // to find the class.
                        c = findClass(name);
                    }
                }
                return c;
        }

         protected final Class findLoadedClass(String name) {
                ClassLoader loader;
                if (this == BootClassLoader.getInstance())
                    loader = null;
                else
                    loader = this;
                return VMClassLoader.findLoadedClass(loader, name);
            }
          //VMClassLoader.findLoadedClass是一个native方法,其实现在art/runtime/native/lava_lang_VMClassLoader: VMClassLoader_findLoadedClass方法



    首次加载类 检察类是否加载过,如果加载过直接返回,由目标classLoader的父类去加载,加载成功直接返回,
    加载失败则再次寻找父类的父类去加载,如果当前类是BootClassLoader则调用VMClassLoader.findLoadedClass去加载,成功则返回,失败则由原始目标classLoader的findClass去加载

    BaseDexClassLoader -> findClass -> pathList.findClass() ->
        //DexPathList
        public Class findClass(String name, List suppressed) {
                for (Element element : dexElements) {
                    Class clazz = element.findClass(name, definingContext, suppressed);
                    if (clazz != null) {
                        return clazz;
                    }
                }

                if (dexElementsSuppressedExceptions != null) {
                    suppressed.addAll(Arrays.asList(dexElementsSuppressedExceptions));
                }
                return null;
            }


2.反射获取类中的dexElements (MutliDex插桩)
    通过反射我们最终可以去修改DexPathList中的dexElements数组 ->   BaseDexClassLoader:pathList(DexPathList):dexElements(Elements[])
        2.1.反射获取BaseDexClassLoader的成员变量pathList(DexPathList)
        2.2.反射获取DexPathList的成员变量dexElements(Elements[])
        2.3.修改dexElements ()

 

你可能感兴趣的:(android)