2016-07-15 54 views
0

我們使用自定義MyClassLoader延伸ClassLoader替換默認PathClassLoader,如:爲什麼MyFragment由PathClassLoader加載不MyClassLoader

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文件inited包含像A1C1類。

PathClassLoader既是MyDexClassLoader也是MyClassLoader的父母。

而且在OriginalApk我們原班A1B1C1

第二問題是,我們可以在loadClass方法打印,即新A1從PatchDex通過MyDexClassLoader(由MyClassLoader稱爲)加載,

但作爲類B1不在PatchDex, MyDexClassLoader(爲什麼不首先由MyClassLoader調用)終於可以用它的父(PathClassLoader)加載老B1

B1類是直接用C1,所以,我們需要加載CLA ss C1。通過打印loadClass方法,我們發現MyDexClassLoader已經控制,但不使用它的PatchDex,只是使用父母的PathClassLoader舊的C1

這是怎麼發生的?爲什麼MyDexClassLoader直接通過它的父級加載C1類,但是它沒有PatchDex?

在此先感謝。

+0

我忘了還有另一個問題,爲什麼'MyClassLoader'不是第一個叫做classloader的呢?有時候'MyDexClassLoader'的'loadClass'直接被調用,而不調用'MyClassLoader'的'loadClass' – oscarthecat

回答

1

andorid for dex中的類加載器與java的類加載器不同。

例如,pathclassloader和dexclassloader不再引用子級。這些類加載器擁有自己的dex文件列表,用於註冊dex文件的加載類。

所以,不要先使用超類。 必須先從您自己的自定義類加載器中找到類。

+0

非常感謝你,你正在拯救我的一天!我加倍檢查了源代碼,它是'私有的最終DexPathList pathList;'在BaseDexClassLoader中,所以所有查找都發現自己的DexPathList pathList。 – oscarthecat

+0

是的,你正確。好工作:D – hanbumpark