EP1-ClassLoader

Hi all,

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


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

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

對(duì)于錢包中這套插件的原理,我大概是有印象的,簡(jiǎn)單描述就是,插件是可以放在宿主中運(yùn)行的apk,但他沒有自己的Activity,需要?jiǎng)e人提供,比如Plugin框架提供的Activity(PluginActivity);然后這個(gè)Activity的生命周期也是傳遞過來的。然后插件所有的新頁面都是Fragment。嗯,大概就是這樣。然后插件的包名根目錄下一定有一個(gè)Plugin.java,它繼承Activityable,接收生命周期,像下面這樣。

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

對(duì)于Module來說呢,也要有一個(gè)HostActivity。以前錢包中有ModuleActivity是插件宿主,繼承自PluginActivity,可以直接setFunctionProvider,現(xiàn)在「Robile化」了,解耦了,ModuleActivity沒有了,取而代之的是module aar中的HostActivity。需要用moduleData保存moduleFunctionProvider(只能是serializable的,不能含有activity對(duì)象;這個(gè)問題的話也許可以考慮使用Parceable解決,這一點(diǎn)以后再討論)。

好了,具體從哪里切入呢。無論是插件化,熱修復(fù)還是動(dòng)態(tài)加載,都涉及到classloader,從這里看起。

0x02 ClassLoader

classloader實(shí)例

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

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)行時(shí)需要加載類到內(nèi)存里。類加載器的實(shí)例不僅有一個(gè)。

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

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

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

嗯,需要傳入一個(gè)parent作為新建的classloader的父母。這樣的話Android系統(tǒng)里所有的classloader實(shí)例都會(huì)關(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)加載過這個(gè)類的的話就返回
            try {
            //2.parent加載過的話,就返回parent加載的類
                clazz = parent.loadClass(className, false);
            } catch (ClassNotFoundException e) {
                // Don't want to see this.
            }

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

        return clazz;
    }

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

-Nov21

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 230,622評(píng)論 6 544
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 99,716評(píng)論 3 429
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 178,746評(píng)論 0 383
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我,道長(zhǎng),這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,991評(píng)論 1 318
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 72,706評(píng)論 6 413
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 56,036評(píng)論 1 329
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼。 笑死,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 44,029評(píng)論 3 450
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 43,203評(píng)論 0 290
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 49,725評(píng)論 1 336
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 41,451評(píng)論 3 361
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 43,677評(píng)論 1 374
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 39,161評(píng)論 5 365
  • 正文 年R本政府宣布,位于F島的核電站,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 44,857評(píng)論 3 351
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,266評(píng)論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,606評(píng)論 1 295
  • 我被黑心中介騙來泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 52,407評(píng)論 3 400
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 48,643評(píng)論 2 380

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

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