EP1-ClassLoader

Hi all颖对,

從今天起我會每天寫郵件給大家發(fā)送日報(bào);日報(bào)的內(nèi)容是每天工作以外學(xué)習(xí)的東西豺妓,比如對組內(nèi)前人寫的代碼的閱讀筆記惜互,或是其他學(xué)到的東西。當(dāng)然這些內(nèi)容對各位老司機(jī)來說大概都是了解過的琳拭,而且由于時間的關(guān)系每天的內(nèi)容可能比較簡短训堆,不妥的部分請指教。另外我的寫作風(fēng)格可能比較啰嗦白嘁,還望見諒坑鱼。。日報(bào)使用Markdown語法編寫, 會同步到我的GitHub Pages絮缅。


下面開始鲁沥。今天的內(nèi)容是關(guān)于股神插件。
股神App開發(fā)的過程中使用了插件耕魄,把錢包中的股神插件作為了股神App唯一的插件画恰,也是robile框架的應(yīng)用。

0x01 插件的話題切入點(diǎn)

對于錢包中這套插件的原理吸奴,我大概是有印象的允扇,簡單描述就是缠局,插件是可以放在宿主中運(yùn)行的apk,但他沒有自己的Activity考润,需要別人提供狭园,比如Plugin框架提供的Activity(PluginActivity);然后這個Activity的生命周期也是傳遞過來的糊治。然后插件所有的新頁面都是Fragment唱矛。嗯,大概就是這樣井辜。然后插件的包名根目錄下一定有一個Plugin.java,它繼承Activityable绎谦,接收生命周期,像下面這樣抑胎。

if (TextUtils.isEmpty(mPluginClass)) {
    if (PluginManager.getInstance().isDebugEnable()) {
        mPluginPackage = PluginActivity.this.getPackageName();
    }
    pluginContextClass = mPluginPackage + ".Plugin";
}

對于Module來說呢燥滑,也要有一個HostActivity。以前錢包中有ModuleActivity是插件宿主阿逃,繼承自PluginActivity铭拧,可以直接setFunctionProvider,現(xiàn)在「Robile化」了恃锉,解耦了搀菩,ModuleActivity沒有了,取而代之的是module aar中的HostActivity破托。需要用moduleData保存moduleFunctionProvider(只能是serializable的肪跋,不能含有activity對象;這個問題的話也許可以考慮使用Parceable解決土砂,這一點(diǎn)以后再討論)州既。

好了,具體從哪里切入呢萝映。無論是插件化吴叶,熱修復(fù)還是動態(tài)加載,都涉及到classloader序臂,從這里看起蚌卤。

0x02 ClassLoader

classloader實(shí)例

PluginActivity中有這樣的代碼,它用loadClass()方法裝載了pluginContextClass奥秆,也就是上面構(gòu)造的.Plugin的那個類:

Class<?> pluginMain = null;
if (!PluginManager.getInstance().isDebugEnable()) {
    pluginMain = mPluginClassLoader.loadClass(pluginContextClass);
} else {
    pluginMain = PluginActivity.this.getClassLoader().loadClass(
            pluginContextClass);
}

loadClass()是什么呢逊彭?它是ClassLoader的方法,用來加載需要的類构订。類似JVM中的defineClass()方法侮叮。
Dalvik/ART虛擬機(jī)跟JVM虛擬機(jī)一樣,運(yùn)行時需要加載類到內(nèi)存里悼瘾。類加載器的實(shí)例不僅有一個签赃。

在Android系統(tǒng)啟動的時候會創(chuàng)建一個Boot類型的ClassLoader實(shí)例谷异,用于加載一些系統(tǒng)Framework層級需要的類,我們的Android應(yīng)用里也需要用到一些系統(tǒng)的類锦聊,所以APP啟動的時候也會把這個Boot類型的ClassLoader傳進(jìn)來。

getClassLoader()可以在程序運(yùn)行過程中讀取到ClassLoader箩绍,classLoader.toString()之后可以看到孔庭,一個APP至少有兩個ClassLoader,也就是上面引用部分提到的兩個材蛛。

Parent-Delegation Model

我們可以自己創(chuàng)建CloassLoader實(shí)例來加載class圆到,構(gòu)造函數(shù)是這樣的:

/*
 * constructor for the BootClassLoader which needs parent to be null.
 */
ClassLoader(ClassLoader parentLoader, boolean nullAllowed) {
    if (parentLoader == null && !nullAllowed) {
        throw new NullPointerException("parentLoader == null && !nullAllowed");
    }
    parent = parentLoader;
}

嗯,需要傳入一個parent作為新建的classloader的父母卑吭。這樣的話Android系統(tǒng)里所有的classloader實(shí)例都會關(guān)聯(lián)在同一棵樹芽淡。這就是Parent-Delegation Model。

Sdk中看到的loadClass()方法:

    protected Class<?> loadClass(String className, boolean resolve) throws ClassNotFoundException {
        Class<?> clazz = findLoadedClass(className);

        if (clazz == null) {//1.classLoader已經(jīng)加載過這個類的的話就返回
            try {
            //2.parent加載過的話豆赏,就返回parent加載的類
                clazz = parent.loadClass(className, false);
            } catch (ClassNotFoundException e) {
                // Don't want to see this.
            }

            if (clazz == null) {
            //3.繼承樹上的classloadler都沒有加載過這個類挣菲,就由child加載這個類
                clazz = findClass(className);
            }
        }

        return clazz;
    }

Sdk源碼里寫得比較清楚,注釋也很翔實(shí)掷邦,這大概是我第一次認(rèn)真看Sdk源碼白胀。掌握閱讀源碼的姿勢是很有必要的。
可以看到抚岗,如果一個類被加載過或杠,那么這個類永遠(yuǎn)不會被重新加載
思考一下宣蔚,這個「永遠(yuǎn)」的期限是什么呢向抢,從前面判斷,系統(tǒng)啟動之后就會有一個系統(tǒng)級別的ClassLoader胚委,app啟動之后會"fork"出一個新的挟鸠,那么加載之后的內(nèi)容會保存在哪里呢,保存的期限是多久呢篷扩。時間關(guān)系兄猩,明天再說吧。

-Nov21

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末鉴未,一起剝皮案震驚了整個濱河市枢冤,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌铜秆,老刑警劉巖淹真,帶你破解...
    沈念sama閱讀 216,324評論 6 498
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異连茧,居然都是意外死亡核蘸,警方通過查閱死者的電腦和手機(jī)巍糯,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,356評論 3 392
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來客扎,“玉大人祟峦,你說我怎么就攤上這事♂阌悖” “怎么了宅楞?”我有些...
    開封第一講書人閱讀 162,328評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長袱吆。 經(jīng)常有香客問我厌衙,道長,這世上最難降的妖魔是什么绞绒? 我笑而不...
    開封第一講書人閱讀 58,147評論 1 292
  • 正文 為了忘掉前任婶希,我火速辦了婚禮,結(jié)果婚禮上蓬衡,老公的妹妹穿的比我還像新娘喻杈。我一直安慰自己,他們只是感情好撤蟆,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,160評論 6 388
  • 文/花漫 我一把揭開白布奕塑。 她就那樣靜靜地躺著,像睡著了一般家肯。 火紅的嫁衣襯著肌膚如雪龄砰。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,115評論 1 296
  • 那天讨衣,我揣著相機(jī)與錄音换棚,去河邊找鬼。 笑死反镇,一個胖子當(dāng)著我的面吹牛固蚤,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播歹茶,決...
    沈念sama閱讀 40,025評論 3 417
  • 文/蒼蘭香墨 我猛地睜開眼夕玩,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了惊豺?” 一聲冷哼從身側(cè)響起燎孟,我...
    開封第一講書人閱讀 38,867評論 0 274
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎尸昧,沒想到半個月后揩页,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,307評論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡烹俗,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,528評論 2 332
  • 正文 我和宋清朗相戀三年爆侣,在試婚紗的時候發(fā)現(xiàn)自己被綠了萍程。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,688評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡兔仰,死狀恐怖茫负,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情乎赴,我是刑警寧澤朽褪,帶...
    沈念sama閱讀 35,409評論 5 343
  • 正文 年R本政府宣布,位于F島的核電站无虚,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏衍锚。R本人自食惡果不足惜友题,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,001評論 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望戴质。 院中可真熱鬧度宦,春花似錦、人聲如沸告匠。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,657評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽后专。三九已至划鸽,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間戚哎,已是汗流浹背裸诽。 一陣腳步聲響...
    開封第一講書人閱讀 32,811評論 1 268
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留型凳,地道東北人丈冬。 一個月前我還...
    沈念sama閱讀 47,685評論 2 368
  • 正文 我出身青樓,卻偏偏與公主長得像甘畅,于是被迫代替她去往敵國和親埂蕊。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,573評論 2 353

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

  • Activity作為四大組件中最重要的組件疏唾,在Replugin中對它的支持的架構(gòu)設(shè)計(jì)也是最復(fù)雜的蓄氧,所以本篇分析我們...
    蔣揚(yáng)海閱讀 10,581評論 2 17
  • 題記 寫這篇關(guān)于Replugin插件化框架的分析,旨在引導(dǎo)讀者去快速的了解RePlugin的大概實(shí)現(xiàn)原理荸实,文中會拋...
    Ihesong閱讀 1,689評論 0 1
  • 早期使用過 Eclipse 等 Java 編寫的軟件的同學(xué)可能比較熟悉匀们,Eclipse 可以加載許多第三方的插件(...
    CHSmile閱讀 1,326評論 0 5
  • RePlugin,360開源的全面插件化框架准给,按照官網(wǎng)說的泄朴,其目的是“盡可能多的讓模塊變成插件”重抖,并在很穩(wěn)定的前提...
    戀貓?jiān)铝?/span>閱讀 33,202評論 29 122
  • 產(chǎn)品特點(diǎn) 互聯(lián)網(wǎng)時代的產(chǎn)品,不同于以往以需求為導(dǎo)向產(chǎn)生的祖灰,而是以產(chǎn)品為導(dǎo)向產(chǎn)生后再引領(lǐng)需求钟沛,當(dāng)需求滿足到一定階段,...
    幽鬼閱讀 674評論 0 2