Android ClassLoader機制

傳統(tǒng)Jvm

java虛擬機把描述類的數(shù)據(jù)從Class文件加載到內(nèi)存朱浴,并對數(shù)據(jù)進行校驗呈昔、轉換解析和初始化,最終形成可以被虛擬機直接使用的Java類型蝶念,這就是虛擬機的類加載機制抛腕。

類的生命周期

類從被加載到虛擬機內(nèi)存中開始芋绸,到卸載出內(nèi)存為止,它的整個生命周期包括:加載(Loading)担敌、驗證(Verification)摔敛、準備(Preparation)、解析(Resolution)全封、初始化(Initialization)马昙、使用(Using)和卸載(Unloading)7個階段。其中驗證刹悴、準備行楞、解析3個部分統(tǒng)稱為連接(Linking),這7個階段的發(fā)生順序如圖所示

image

類加載器

對于任意一個類土匀,都需要由加載它的類加載器和這個類本身一同確立其在Java虛擬機中的唯一性子房,每一個類加載器,都擁有一個獨立的類名稱空間就轧。這句話可以表達得更通俗一些:**比較兩個類是否“相等”池颈,只有在這兩個類是由同一個類加載器加載的前提下才有意義,否則钓丰,即使這兩個類來源于同一個Class文件躯砰,被同一個虛擬機加載,只要加載它們的類加載器不同携丁,那這兩個類就必定不相等琢歇。 **

雙親委派模型

絕大部分Java程序都會使用到以下3種系統(tǒng)提供的類加載器:

  1. 啟動類加載器(Bootstrap ClassLoader)

這個類將器負責將存放在<JAVA_HOME>\lib目錄中的,或者被-Xbootclasspath參數(shù)所指定的路徑中的梦鉴,并且是虛擬機識別的(僅按照文件名識別李茫,如rt.jar,名字不符合的類庫即使放在lib目錄中也不會被加載)類庫加載到虛擬機內(nèi)存中肥橙。啟動類加載器無法被Java程序直接引用魄宏,用戶在編寫自定義類加載器時,如果需要把加載請求委派給引導類加載器存筏,那直接使用null代替即可宠互。

  1. 擴展類加載器(Extension ClassLoader)

這個加載器由sun.misc.Launcher $ExtClassLoader實現(xiàn),它負責加載<JAVA_HOME>\lib\ext目錄中的椭坚,或者被java.ext.dirs系統(tǒng)變量所指定的路徑中的所有類庫予跌,開發(fā)者可以直接使用擴展類加載器。

  1. 應用程序類加載器(Application ClassLoader)

這個類加載器由sun.misc.Launcher $App-ClassLoader實現(xiàn)善茎。由于這個類加載器是ClassLoader中的getSystemClassLoader()方法的返回值券册,所以一般也稱它為系統(tǒng)類加載器。它負責加載用戶類路徑(ClassPath)上所指定的類庫,開發(fā)者可以直接使用這個類加載器烁焙,如果應用程序中沒有自定義過自己的類加載器航邢,一般情況下這個就是程序中默認的類加載器。

java應用程序一般都是由這3種類加載器互相配合進行加載的骄蝇,如果有必要膳殷,還可以加入自己定義的類加載器。這些類加載器之間的關系一般如圖所示乞榨。

image

上圖中展示的類加載器之間的這種層次關系秽之,稱為類加載器的雙親委派模型(Parents Delegation Model)当娱。雙親委派模型要求除了頂層的啟動類加載器外吃既,其余的類加載器都應當有自己的父類加載器。這里類加載器之間的父子關系一般不會以繼承(Inheritance)的關系來實現(xiàn)跨细,而是都使用組合(Composition)關系來復用父加載器的代碼鹦倚。

雙親委派模型的工作過程是:如果一個類加載器收到了類加載的請求,它首先不會自己去嘗試加載這個類冀惭,而是把這個請求委派給父類加載器去完成震叙,每一個層次的類加載器都是如此,因此所有的加載請求最終都應該傳送到頂層的啟動類加載器中散休,只有當父加載器反饋自己無法完成這個加載請求(它的搜索范圍中沒有找到所需的類)時媒楼,子加載器才會嘗試自己去加載。

Android的ClassLoader機制

本質上戚丸,Android和傳統(tǒng)的JVM是一樣的划址,也需要通過ClassLoader 將目標類加載到內(nèi)存,類加載器之間也符合雙親委派模型限府,類也有對應的生命周期夺颤。但基于移動設備的特點,如內(nèi)存以及電量等諸多方面跟一般的 PC 設備都有本質的區(qū)別胁勺,Google開發(fā)了更符合移動設備的用于執(zhí)行 Java 代碼的虛擬機世澜,也就是Dalvik和 ART,Android從5.0開始就采用AR虛擬機替代Dalvik署穗。傳統(tǒng)Jvm主要是通過讀取class字節(jié)碼來加載, 而ART則是從dex字節(jié)碼來讀取. 這是一種更為優(yōu)化的方案, 可以將多個.class文件合并成一個classes.dex文件寥裂。

Classloader關系圖

image

BaseDexClassLoader

public class BaseDexClassLoader extends ClassLoader {
    private final DexPathList pathList;
    public BaseDexClassLoader(String dexPath, File optimizedDirectory,
            String librarySearchPath, ClassLoader parent) {
        super(parent);
        this.pathList = new DexPathList(this, dexPath, librarySearchPath, null);
    }
    @Override
    protected Class<?> findClass(String name) throws ClassNotFoundException {
        ...
        ...
        Class c = pathList.findClass(name, suppressedExceptions);
        ...
        ...
        return c;
    }
    @Override
    protected URL findResource(String name) {
        return pathList.findResource(name);
    }
    @Override
    public String findLibrary(String name) {
        return pathList.findLibrary(name);
    }
}

可以看到在構造函數(shù)里初始化了DexPathList對象瘟斜,而在BaseDexClassLoader中的操作findClass锐涯、findResource執(zhí)行的都是這個DexPathList對象的操作鼠冕,關于DexPathList飘哨,在此暫不展開梅割。

從DexPathList的構造過程可以看到乃坤,無論optimizedDirectory是何值陶贼,傳遞的都是空悦荒,所以optimizedDirectory參數(shù)是無效的(從Android8.0開始)

PathClassLoader

public class PathClassLoader extends BaseDexClassLoader {

    public PathClassLoader(String dexPath, ClassLoader parent) {
        super(dexPath, null, null, parent);
    }

    public PathClassLoader(String dexPath, String librarySearchPath, ClassLoader parent) {
        super(dexPath, null, librarySearchPath, parent);
    }
}

PathClassLoader比較簡單, 繼承于BaseDexClassLoader. 默認 optimizedDirectory=null.

DexClassLoader

public class DexClassLoader extends BaseDexClassLoader {
    public DexClassLoader(String dexPath, String optimizedDirectory,
            String librarySearchPath, ClassLoader parent) {
        super(dexPath, null, librarySearchPath, parent);
    }
}

DexClassLoader也比較簡單, 只是簡單封裝,和PathClassLoader唯一區(qū)別就是多了optimizedDirectory參數(shù),但從上面BaseDexClassLoader分析可以知道混萝,從8.0開始optimizedDirectory已經(jīng)棄用遗遵。從理論上來說,PathClassLoader應該可以完全替代DexClassLoader逸嘀。但網(wǎng)上有這樣的結論:

DexClassLoader:能夠加載未安裝的apk
PathClassLoader:只能加載系統(tǒng)中已經(jīng)安裝過的apk

那么在8.0以上這個結論還成立嗎车要,事實上PathClassLoader也可以加載未安裝的apk,驗證過程比較簡單崭倘,不在此累贅翼岁,有興趣可以自己試試。

參考

http://www.reibang.com/p/78f9a3f55f56

?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末司光,一起剝皮案震驚了整個濱河市琅坡,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌残家,老刑警劉巖榆俺,帶你破解...
    沈念sama閱讀 206,311評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異坞淮,居然都是意外死亡茴晋,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,339評論 2 382
  • 文/潘曉璐 我一進店門回窘,熙熙樓的掌柜王于貴愁眉苦臉地迎上來诺擅,“玉大人,你說我怎么就攤上這事啡直∷赣浚” “怎么了?”我有些...
    開封第一講書人閱讀 152,671評論 0 342
  • 文/不壞的土叔 我叫張陵付枫,是天一觀的道長烹玉。 經(jīng)常有香客問我,道長阐滩,這世上最難降的妖魔是什么二打? 我笑而不...
    開封第一講書人閱讀 55,252評論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮掂榔,結果婚禮上继效,老公的妹妹穿的比我還像新娘。我一直安慰自己装获,他們只是感情好瑞信,可當我...
    茶點故事閱讀 64,253評論 5 371
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著穴豫,像睡著了一般凡简。 火紅的嫁衣襯著肌膚如雪逼友。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,031評論 1 285
  • 那天秤涩,我揣著相機與錄音帜乞,去河邊找鬼。 笑死筐眷,一個胖子當著我的面吹牛黎烈,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播匀谣,決...
    沈念sama閱讀 38,340評論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼照棋,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了武翎?” 一聲冷哼從身側響起烈炭,我...
    開封第一講書人閱讀 36,973評論 0 259
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎后频,沒想到半個月后梳庆,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體暖途,經(jīng)...
    沈念sama閱讀 43,466評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡卑惜,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 35,937評論 2 323
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了驻售。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片露久。...
    茶點故事閱讀 38,039評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖欺栗,靈堂內(nèi)的尸體忽然破棺而出毫痕,到底是詐尸還是另有隱情,我是刑警寧澤迟几,帶...
    沈念sama閱讀 33,701評論 4 323
  • 正文 年R本政府宣布消请,位于F島的核電站,受9級特大地震影響类腮,放射性物質發(fā)生泄漏臊泰。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,254評論 3 307
  • 文/蒙蒙 一蚜枢、第九天 我趴在偏房一處隱蔽的房頂上張望缸逃。 院中可真熱鬧,春花似錦厂抽、人聲如沸需频。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,259評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽昭殉。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間挪丢,已是汗流浹背莽鸭。 一陣腳步聲響...
    開封第一講書人閱讀 31,485評論 1 262
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留吃靠,地道東北人硫眨。 一個月前我還...
    沈念sama閱讀 45,497評論 2 354
  • 正文 我出身青樓,卻偏偏與公主長得像巢块,于是被迫代替她去往敵國和親礁阁。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 42,786評論 2 345

推薦閱讀更多精彩內(nèi)容