Android之ClassLoader的工做機制

ClassLoader雙親代理模型加載類的特色及做用

JVM以及Dalvik均是經過ClassLoader加載類,其源碼以下
protected Class<?> loadClass(String className, boolean resolve) throws ClassNotFoundException {
Class<?> clazz = findLoadedClass(className);

if (clazz == null) {
ClassNotFoundException suppressed = null;
try {
clazz = parent.loadClass(className, false);
} catch (ClassNotFoundException e) {
suppressed = e;
}

if (clazz == null) {
try {
clazz = findClass(className);
} catch (ClassNotFoundException e) {
e.addSuppressed(suppressed);
throw e;
}
}
}

return clazz;
}
從源碼分析可知loadClass方法先判斷是否被loaded過,沒有則經過parent加載,如此遞歸向上,稱之位雙親委託。若是繼承向上的路線中均沒有被加載,才由當前ClassLoader負責加載。
特色:若某個類被根節點加載過,則在之後系統的整個生命週期內不會被從新加載。
做用:
    1.共享:Framework層級的類一旦被根節點加載就緩存在內存,之後不需從新加載。
    2.隔離:不一樣繼承路線上的classLoader加載的類確定不是同一個類,這樣作可避免冒充核心庫類,從而訪問核心庫包可見成員。例如,用戶沒法經過自定義java.lang.String類,來把系統的String類給替換掉。

Android應用中的ClassLoader對象

在Activity的onCreate方法中調用
ClassLoader classLoader = getClassLoader();
if (classLoader != null) {
lg.e("當前類對應的ClassLoader:" + classLoader.toString());
while (classLoader.getParent() != null) {
classLoader = classLoader.getParent();
lg.e("上個ClassLoader的父親:" + classLoader.toString());
}
}
輸出結果以下,

其中,BootClassLoader在系統啓動時建立,PathClassLoader在應用啓動時建立,用於加載/data/app/com.coca.androidunitylab-1.apk。所以在一個應用中至少有兩個classLoader。


DexClassLoader與PathClassLoader的異同

適用場景:
     DexClassLoader能夠加載jar/apk/dex,能夠從SD卡中加載未安裝的apk;
    PathClassLoader只能加載系統中已經安裝過的apk;
二者的區別在於 optimizedDirectory參數,其在 BaseDexClassLoader構造方法中用於構建 DexPathList對象。
optimizedDirectory用來緩存須要加載的dex文件,並建立一個DexFile對象;若是它爲null,那麼會直接使用dex文件原有的路徑來建立DexFile對象。 optimizedDirectory必須是內部存儲路徑 DexClassLoader因爲能夠指定 optimizedDirectory,從而能夠加載外部dex,在使用的時候被複制到內部路徑 optimizedDirectory內;而 PathClassLoader沒指定 optimizedDirectory,所以只能加載內部dex文件(即已經安裝的apk文件)。













相關文章
相關標籤/搜索