Android 類加載模式

類圖

 28668c5a-86e4-41ac-9ea3-9f7a4fb8b46f.png

相關類介紹

BootClassLoader

調用流程
1、ZygoteInit的main方法
2、預加載常用類
3、讀取預加載類名時獲取BootClassLoader單例
4、調用classForName(C實現)獲取結果

DexClassLoader

構造函數
public DexClassLoader (String dexPath, String dexOutputDir, String libPath, ClassLoader parent)
optimizedDirectory是用來緩存我們需要加載的dex文件的,並創建一個DexFile對象,如果它爲null,那麼會直接使用dex文件原有的路徑來創建DexFile  
DexClassLoader可以指定自己的optimizedDirectory,所以它可以加載外部的dex,因爲這個dex會被複制到內部路徑的optimizedDirectory
注意:該加載器能夠加載未安裝的jar/apk/dex

PathClassLoader

構造函數
public PathClassLoader (String path, String libPath, ClassLoader parent)
調用流程
1、Zygote進程啓動SyetemServer進程
2、ZygoteInit的startSystemServer方法
3、Zygote進程通過forkSystemServer方法fork自身創建子進程並且調用handleSystemServerProcess
4、 工廠方法創建PathClassLoader
注意:該加載器只能加載系統中已經安裝過的apk

SecureClassLoader和URLClassLoader

SecureClassLoader類和JDK8中的SecureClassLoader類的代碼是一樣的,它繼承了抽象類ClassLoader。SecureClassLoader並不是ClassLoader的實現類,而是拓展了ClassLoader類加入了權限方面的功能,加強了ClassLoader的安全性。
URLClassLoader類和JDK8中的URLClassLoader類的代碼是一樣的,它繼承自SecureClassLoader,用來通過URl路徑從jar文件和文件夾中加載類和資源。

InMemoryDexClassLoader

InMemoryDexClassLoader是Android8.0新增的類加載器,繼承自BaseDexClassLoader,用於加載內存中的dex文件。

具體加載源碼

  • 從已裝載過的類中找

  • 如果從已裝載過的列表中找不到,則從父類裝載

  • 如果父類找不到,從子類裝載

    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;
    }

    public Class findClass(String name, List suppressed) {
    for (Element element : dexElements) {//這裏進行遍歷查詢
    DexFile dex = element.dexFile;

            if (dex != null) {
               //從DexFile中試圖加載Class,從這裏看出,從第一個開始遍歷,如果查到就返回,這就是熱修復的基本原理。
                Class clazz = dex.loadClassBinaryName(name, definingContext, suppressed);
                if (clazz != null) {
                    return clazz;
                }
            }
        }
        //..
        return null;
    }
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章