为什么MyFragment由PathClassLoader加载而不是MyClassLoader

时间:2016-07-15 11:39:18

标签: android classloader patch

我们使用自定义MyClassLoader扩展ClassLoader来替换默认PathClassLoader,例如:

    Context mBase = (Context) getFieldValue(application, "mBase");
    Object mPackageInfo = getFieldValue(mBase, "mPackageInfo");
    ORIGINAL_CLASS_LOADER = (ClassLoader) getFieldValue(mPackageInfo, "mClassLoader");
    CUSTOMED_CLASS_LOADER = new MyClassLoader(ORIGINAL_CLASS_LOADER);
当应用程序处于onCreat时执行

第一个问题是,并非所有类都由MyClassLoader首先加载,只有MyActivitysMyViewsMyClassLoader加载,MyFragments仍在加载按PathClassLoader。这与Context有什么关系吗?

MyClassLoader我们按

加载课程
    public Class<?> loadClass(String className)
            throws ClassNotFoundException {
        try {
            ClassLoader myDexClassLoader = loaders.get("DEX");
            if(myDexClassLoader != null){
                Class<?> c = null;
                try {
                     c = myDexClassLoader.loadClass(className);
                    // c = loader.findClass(className);
                } catch (ClassNotFoundException e) {
                }
                if (c != null) {
                    return c;
                }
            }
        } 
        return super.loadClass(className);
    }`

myDexClassLoader 定义为

    public static class MyDexClassLoader extends DexClassLoader {

    public MyDexClassLoader(String dexPath, String dexOutputDir,
            String libPath, ClassLoader parent) {
        super(dexPath, dexOutputDir, libPath, parent);
    }

    @Override
    protected Class<?> findClass(String name) throws ClassNotFoundException {
        return super.findClass(name);
    }

    @SuppressLint("NewApi")
    @Override
    public Class<?> loadClass(String className)
            throws ClassNotFoundException {
        Class<?> clazz = null;
        try {
            clazz = findClass(className);
        } catch (ClassNotFoundException e) {
        }
        if (clazz != null) {
            return clazz;
        }
        return super.loadClass(className);
    }

}

MyDexClassLoader与PatchDex文件一起包含 A1 C1 等类。

PathClassLoaderMyDexClassLoaderMyClassLoader的父母。

在OriginalApk中,我们有原始类 A1 B1 C1

第二个问题是,我们可以使用loadClass方法打印,MyDexClassLoaderMyClassLoader(由MyDexClassLoader调用)从PatchDex加载新A1

但由于 B1 类不在PatchDex中,MyClassLoader(为什么不首先由PathClassLoader调用)最终使用它的父(MyDexClassLoader)来加载旧B1

B1类直接使用C1,所以我们必须加载C1类。通过print loadClass方法,我们发现PathClassLoader已经取得了控制权,但没有使用它的PatchDex,只使用了父MyDexClassLoader旧C1

这是怎么发生的?为什么setUp直接由它的父级加载C1类,但是当它有PatchDex时它不是?

提前致谢。

1 个答案:

答案 0 :(得分:1)

dex的andorid中的类加载器与java的类加载器不同。

例如,pathclassloader和dexclassloader不再引用child。这些类加载器有自己的dex文件列表,用于从已注册的dex文件加载类。

所以,不要先使用超类。 必须首先从您自己的自定义类加载器中找到类。