Android類加載(二)——雙親委托機制

Android類加載(一)——DVM僚纷、ART烫扼、Dexopt、DexAot名詞解析
Android類加載(二)——雙親委托機制
Android類加載(三)——源碼解讀

Java類加載器

定義
  • BootClassLoader
    用于加載Android FrameWork層的class文件(系統(tǒng)的Activity)
  • PathClassLoader
    用于加載Android應(yīng)用程序的class 文件(自己寫的MainActivity)
    也可以加載指定的dex浩考,以及jar廊移、zip、apk中的classes.dex
  • DexClassLoader
    加載指定的dex舵鳞,以及jar震檩、zip、apk中的classes.dex

比較PathClassLoader和DexClassLoader

  • 在一個app安裝的過程中蜓堕,Android系統(tǒng)是沒有用到DexClassLoader類的抛虏,而PathClassLoader會被用于加載Android應(yīng)用程序的class 文件(例如自己寫的MainActivity),DexClassLoader類就是提供給開發(fā)者使用的類套才,Android FrameWork層并沒有使用到DexClassLoader迂猴。
  • 構(gòu)造方法的區(qū)別
public class DexClassLoader extends BaseDexClassLoader {
    /**
     * Creates a {@code DexClassLoader} that finds interpreted and native
     * code.  Interpreted classes are found in a set of DEX files contained
     * in Jar or APK files.
     *
     * <p>The path lists are separated using the character specified by the
     * {@code path.separator} system property, which defaults to {@code :}.
     *
     * @param dexPath the list of jar/apk files containing classes and
     *     resources, delimited by {@code File.pathSeparator}, which
     *     defaults to {@code ":"} on Android
     * @param optimizedDirectory directory where optimized dex files
     *     should be written; must not be {@code null}
     * @param libraryPath the list of directories containing native
     *     libraries, delimited by {@code File.pathSeparator}; may be
     *     {@code null}
     * @param parent the parent class loader
     */
    public DexClassLoader(String dexPath, String optimizedDirectory,
            String libraryPath, ClassLoader parent) {
        super(dexPath, new File(optimizedDirectory), libraryPath, parent);
    }
}
public class PathClassLoader extends BaseDexClassLoader {
    /**
     * Creates a {@code PathClassLoader} that operates on a given list of files
     * and directories. This method is equivalent to calling
     * {@link #PathClassLoader(String, String, ClassLoader)} with a
     * {@code null} value for the second argument (see description there).
     *
     * @param dexPath the list of jar/apk files containing classes and
     * resources, delimited by {@code File.pathSeparator}, which
     * defaults to {@code ":"} on Android
     * @param parent the parent class loader
     */
    public PathClassLoader(String dexPath, ClassLoader parent) {
        super(dexPath, null, null, parent);
    }

    /**
     * Creates a {@code PathClassLoader} that operates on two given
     * lists of files and directories. The entries of the first list
     * should be one of the following:
     *
     * <ul>
     * <li>JAR/ZIP/APK files, possibly containing a "classes.dex" file as
     * well as arbitrary resources.
     * <li>Raw ".dex" files (not inside a zip file).
     * </ul>
     *
     * The entries of the second list should be directories containing
     * native library files.
     *
     * @param dexPath the list of jar/apk files containing classes and
     * resources, delimited by {@code File.pathSeparator}, which
     * defaults to {@code ":"} on Android
     * @param libraryPath the list of directories containing native
     * libraries, delimited by {@code File.pathSeparator}; may be
     * {@code null}
     * @param parent the parent class loader
     */
    public PathClassLoader(String dexPath, String libraryPath,
            ClassLoader parent) {
        super(dexPath, null, libraryPath, parent);
    }
}

從源碼里可以看出它們都派生于BaseDexClassLoader類,但在它們的構(gòu)造方法稍有不同

public DexClassLoader(String dexPath, String optimizedDirectory,
            String libraryPath, ClassLoader parent) {
        super(dexPath, new File(optimizedDirectory), libraryPath, parent);
    }
public PathClassLoader(String dexPath, String libraryPath,
           ClassLoader parent) {
       super(dexPath, null, libraryPath, parent);
   }

有三個參數(shù)是一樣的

  • dexPath:要加載的dex所在的目錄
  • libraryPath:Native方法so文件所在的目錄
  • parent:可以理解為雙親加載機制里的所謂的“父親”(雙親委托機制下面再講)
  • optimizedDirectory:opt優(yōu)化后的dex文件所在的目錄(而且從源碼的注釋里可以看到背伴,這個目錄必須為私有目錄沸毁,不能為sd卡的目錄)

而DexClassLoader就比PathClassLoader多了一個optimizedDirectory參數(shù),
也就是說DexClassLoader用于存儲opt優(yōu)化后的dex文件的保存路徑可以自己定義傳進去傻寂,而PathClassLoader存儲opt優(yōu)化后的dex文件的保存路徑是系統(tǒng)默認的息尺。僅此這個區(qū)別而已。

雙親委托機制

類加載在加載類時疾掰,首先將加載任務(wù)委托給父類加載器加載搂誉,依次遞歸,如果父類加載器可以完成加載任務(wù)静檬,就成功返回炭懊,如果父類加載器無法完成或者沒有父類加載器時,才自己去加載拂檩。
簡單一個詞語概括:啃老族機制侮腹。

下面我們用一段代碼來進行解釋:


public class MainActivity extends AppCompatActivity {


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        //PathClassLoader
        ClassLoader classLoader = this.getClassLoader();
        //BootClassLoader
        ClassLoader classLoader1 = Activity.class.getClassLoader();
        
        System.out.println("PathClassLoader getClassLoader:"+classLoader);
        System.out.println("PathClassLoader getClassLoader 的父親 :"+classLoader.getParent());
        System.out.println("BootClassLoader Activity.class :"+classLoader1);

image.png

從打印中我們可以得出以下結(jié)論

  • MainActivity的類加載器是PathClassLoader
  • Activity的類加載器是PathClassLoader
  • PathClassLoader的父親是BootClassLoader

注意:這里所說的父親并不是指這個類的父類(BaseDexClassLoader),只是ClassLoder類里的一個類型為ClassLoader的成員變量名稱叫做parent

image.png

image.png
那么為什么要使用雙親委托機制呢稻励?

在我們應(yīng)用程序啟動的時候父阻,BootClassLader會去加載FrameWork層的所有的類,例如上面的Activity钉迷,而我們自己寫的代碼BootClassLader是沒辦法去加載的至非,只能由PathClassLoader去加載,因為我們自己寫的代碼的類糠聪,在我們的apk里面荒椭,不在系統(tǒng)里面,例如上面的MainActivity舰蟆。但現(xiàn)在我們寫的MainActivity是派生于AppCompatActivity的趣惠,AppCompatActivity屬于FrameWork層的類狸棍,已經(jīng)被BootClassLader加載了,如果我們不使用雙親委托機制的話味悄,PathClassLoader是不是加載不到FrameWork層的類草戈,那是不是加載不了AppCompatActivity了,而運用雙親委托機制就能很好的讓不同的類加載器去分別執(zhí)行不同層級的類加載的任務(wù)侍瑟,這樣也是有利于系統(tǒng)的安全性唐片,對于開發(fā)者來說你是無法知道怎么去加載系統(tǒng)的類的,你永遠只能加載自己寫的類涨颜,系統(tǒng)層面的類是不讓你去加載的费韭,只能由父親BootClassLader去加載。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末庭瑰,一起剝皮案震驚了整個濱河市星持,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌弹灭,老刑警劉巖督暂,帶你破解...
    沈念sama閱讀 222,464評論 6 517
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異穷吮,居然都是意外死亡逻翁,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,033評論 3 399
  • 文/潘曉璐 我一進店門捡鱼,熙熙樓的掌柜王于貴愁眉苦臉地迎上來卢未,“玉大人,你說我怎么就攤上這事堰汉。” “怎么了伟墙?”我有些...
    開封第一講書人閱讀 169,078評論 0 362
  • 文/不壞的土叔 我叫張陵翘鸭,是天一觀的道長。 經(jīng)常有香客問我戳葵,道長就乓,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 59,979評論 1 299
  • 正文 為了忘掉前任拱烁,我火速辦了婚禮生蚁,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘戏自。我一直安慰自己邦投,他們只是感情好,可當我...
    茶點故事閱讀 69,001評論 6 398
  • 文/花漫 我一把揭開白布擅笔。 她就那樣靜靜地躺著志衣,像睡著了一般屯援。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上念脯,一...
    開封第一講書人閱讀 52,584評論 1 312
  • 那天狞洋,我揣著相機與錄音,去河邊找鬼绿店。 笑死吉懊,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的假勿。 我是一名探鬼主播借嗽,決...
    沈念sama閱讀 41,085評論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼废登!你這毒婦竟也來了淹魄?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 40,023評論 0 277
  • 序言:老撾萬榮一對情侶失蹤堡距,失蹤者是張志新(化名)和其女友劉穎甲锡,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體羽戒,經(jīng)...
    沈念sama閱讀 46,555評論 1 319
  • 正文 獨居荒郊野嶺守林人離奇死亡缤沦,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,626評論 3 342
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了易稠。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片缸废。...
    茶點故事閱讀 40,769評論 1 353
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖驶社,靈堂內(nèi)的尸體忽然破棺而出企量,到底是詐尸還是另有隱情,我是刑警寧澤亡电,帶...
    沈念sama閱讀 36,439評論 5 351
  • 正文 年R本政府宣布届巩,位于F島的核電站,受9級特大地震影響份乒,放射性物質(zhì)發(fā)生泄漏恕汇。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 42,115評論 3 335
  • 文/蒙蒙 一或辖、第九天 我趴在偏房一處隱蔽的房頂上張望瘾英。 院中可真熱鬧,春花似錦颂暇、人聲如沸缺谴。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,601評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽瓣赂。三九已至榆骚,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間煌集,已是汗流浹背妓肢。 一陣腳步聲響...
    開封第一講書人閱讀 33,702評論 1 274
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留苫纤,地道東北人碉钠。 一個月前我還...
    沈念sama閱讀 49,191評論 3 378
  • 正文 我出身青樓,卻偏偏與公主長得像卷拘,于是被迫代替她去往敵國和親喊废。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 45,781評論 2 361