類(lèi)加載概念

提到類(lèi)加載的概念屡拨,很多朋友可能會(huì)問(wèn),什么是類(lèi)加載褥实?類(lèi)加載了解后對(duì)我們的測(cè)試開(kāi)發(fā)工作有什么幫助呀狼?在此,我們想先集中整理第一個(gè)問(wèn)題损离,第二個(gè)問(wèn)題只能慢慢體會(huì)哥艇。


什么是類(lèi)加載?

首先僻澎,是種機(jī)制貌踏!代碼要運(yùn)行須得先經(jīng)過(guò)編譯,編譯后在工程目錄中會(huì)產(chǎn)生一堆*.class文件(這種文件是二進(jìn)制流文件)窟勃;而當(dāng)JVM把這些*.class文件(里面包含類(lèi)的描述數(shù)據(jù)祖乳,這個(gè)描述數(shù)據(jù)暫且可理解為JVM識(shí)別的一種約定規(guī)范)加載到內(nèi)存中,并且伴隨對(duì)數(shù)據(jù)進(jìn)行校驗(yàn)秉氧、轉(zhuǎn)換解析眷昆、初始化,最終成為被JVM直接使用的Java類(lèi)型,這個(gè)過(guò)程叫Java的類(lèi)記載機(jī)制亚斋。


類(lèi)加載包含哪些過(guò)程作媚?

1、類(lèi)的加載(此類(lèi)非彼類(lèi))帅刊,包含3環(huán)節(jié):

? a. 根據(jù)類(lèi)名或者包名來(lái)獲取二進(jìn)制流文件纸泡;

? b. 將字節(jié)流文件所代表的靜態(tài)數(shù)據(jù)結(jié)構(gòu)轉(zhuǎn)化為方法區(qū)的運(yùn)行時(shí)的數(shù)據(jù)結(jié)構(gòu);此處只是做了數(shù) 據(jù)結(jié)構(gòu)的轉(zhuǎn)化厚掷,不含有數(shù)據(jù)的合并弟灼;(如何理解什么是方法區(qū)的運(yùn)行時(shí)的數(shù)據(jù)結(jié)構(gòu)? 方法區(qū)就是用來(lái)存放已被加載的類(lèi)信息冒黑,常量田绑,靜態(tài)變量,編譯后的代碼的運(yùn)行時(shí)內(nèi)存區(qū)域)抡爹;

? c. 在內(nèi)存中生成一個(gè)代表這個(gè)類(lèi)的java.lang.Class對(duì)象掩驱,作為方法區(qū)這個(gè)類(lèi)的各種數(shù)據(jù)的訪問(wèn)入口;這個(gè)對(duì)象不存在于堆內(nèi)存中冬竟,而是存在于方法區(qū)中欧穴;

2、類(lèi)的連接

? ? 連接階段負(fù)責(zé)將類(lèi)的二進(jìn)制數(shù)據(jù)合并入JRE(Java運(yùn)行時(shí)環(huán)境)中泵殴。也包含3個(gè)環(huán)節(jié):

? ? a. 驗(yàn)證被加載后的類(lèi)是否有正確的結(jié)構(gòu)

? ? b. 準(zhǔn)備:給靜態(tài)變量分配內(nèi)存和賦初值

? ? c. 解析:二進(jìn)制數(shù)據(jù)中的符號(hào)引用換為直接引用涮帘。

3、類(lèi)的初始化 (真正執(zhí)行Java代碼的階段)

? ? 類(lèi)的初始化的主要工作是為靜態(tài)變量賦程序設(shè)定的初值笑诅。

類(lèi)加載的各個(gè)階段

類(lèi)加載器

在上文中講到的第一個(gè)過(guò)程中有一個(gè)重要的代碼塊不得不提调缨,就是“類(lèi)加載器”;當(dāng)然類(lèi)加載器的重要作用不單單只是負(fù)責(zé)實(shí)現(xiàn)類(lèi)的加載吆你,它還與類(lèi)的“相等”判定有關(guān)弦叶,關(guān)系著Java“相等”判定方法的返回結(jié)果,只有在滿(mǎn)足如下三個(gè)“相等”判定條件妇多,才能判定兩個(gè)類(lèi)相等伤哺。

1、兩個(gè)類(lèi)來(lái)自同一個(gè)Class文件

2者祖、兩個(gè)類(lèi)是由同一個(gè)虛擬機(jī)加載

3立莉、兩個(gè)類(lèi)是由同一個(gè)類(lèi)加載器加載

Java“相等”判定相關(guān)方法:

1、判斷兩個(gè)實(shí)例對(duì)象的引用是否指向內(nèi)存中同一個(gè)實(shí)例對(duì)象七问,使用 Class對(duì)象的equals()方法桃序,obj1.equals(obj2);

2烂瘫、判斷實(shí)例對(duì)象是否為某個(gè)類(lèi)、接口或其子類(lèi)、子接口的實(shí)例對(duì)象坟比,使用Class對(duì)象的isInstance()方法芦鳍,class.isInstance(obj);

3葛账、判斷實(shí)例對(duì)象是否為某個(gè)類(lèi)柠衅、接口的實(shí)例,使用instanceof關(guān)鍵字籍琳,obj instanceof class菲宴;

4、判斷一個(gè)類(lèi)是否為另一個(gè)類(lèi)本身或其子類(lèi)趋急、子接口喝峦,可以使用Class對(duì)象的isAssignableFrom()方法,class1.isAssignableFrom(class


JVM類(lèi)加載器分類(lèi)詳解:

1呜达、Bootstrap ClassLoader:?jiǎn)?dòng)類(lèi)加載器谣蠢,也叫根類(lèi)加載器,它負(fù)責(zé)加載Java的核心類(lèi)庫(kù)查近,它不是java.lang.ClassLoader的子類(lèi)眉踱,它是JVM自身內(nèi)部由C/C++實(shí)現(xiàn)的,并不是Java實(shí)現(xiàn)的

2霜威、Extension ClassLoader:擴(kuò)展類(lèi)加載器谈喳,負(fù)責(zé)核心類(lèi)以外的新功能擴(kuò)展類(lèi)的加載

3、System ClassLoader:系統(tǒng)類(lèi)加載器或稱(chēng)為應(yīng)用程序類(lèi)加載器戈泼,是加載CLASSPATH環(huán)境變量所指定的jar包與類(lèi)路徑

4婿禽、APP ClassLoader:用戶(hù)自定義的類(lèi)加載。

類(lèi)加載器的雙親委派加載機(jī)制:

百度文庫(kù)引用

加載機(jī)制主要體現(xiàn)在ClassLoader的loadClass()方法中矮冬,思路很簡(jiǎn)單:先檢查是否已經(jīng)被加載過(guò)谈宛,若沒(méi)有加載則調(diào)用父類(lèi)加載器的loadClass()方法,若父類(lèi)加載器為空則默認(rèn)使用啟動(dòng)類(lèi)加載器作為父類(lèi)加載器胎署。如果父類(lèi)加載器加載失敗吆录,拋出ClassNotFoundException異常后,調(diào)用自己的findClass()方法進(jìn)行加載琼牧。

說(shuō)明:System類(lèi)與List(ArrayList繼承自該類(lèi))類(lèi)都屬于Java核心類(lèi)恢筝,由啟動(dòng)類(lèi)加載器加載,而啟動(dòng)類(lèi)加載器是在JVM內(nèi)部通過(guò)C/C++實(shí)現(xiàn)的巨坊,并不是Java撬槽,自然也就不能繼承ClassLoader類(lèi),自然就不能輸出其名稱(chēng)了趾撵。


最后一個(gè)問(wèn)題:

1侄柔、雙親委派加載機(jī)制的命名由來(lái)共啃,為什么不叫“單親委派記載機(jī)制”?

2暂题、委托機(jī)制的意義 ( 防止內(nèi)存中出現(xiàn)多份同樣的字節(jié)碼)

比如兩個(gè)類(lèi)A和類(lèi)B都要加載System類(lèi):如果不用委托而是自己加載自己的移剪,那么類(lèi)A就會(huì)加載一份System字節(jié)碼,然后類(lèi)B又會(huì)加載一份System字節(jié)碼薪者,這樣內(nèi)存中就出現(xiàn)了兩份System字節(jié)碼纵苛。如果使用委托機(jī)制,會(huì)遞歸的向父類(lèi)查找言津,也就是首選用Bootstrap嘗試加載攻人,如果找不到再向下。這里的System就能在Bootstrap中找到然后加載悬槽,如果此時(shí)類(lèi)B也要加載System怀吻,也從Bootstrap開(kāi)始,此時(shí)Bootstrap發(fā)現(xiàn)已經(jīng)加載過(guò)了System那么直接返回內(nèi)存中的System即可而不需要重新加載陷谱,這樣內(nèi)存中就只有一份System的字節(jié)碼了烙博。

3、能不能自己寫(xiě)個(gè)類(lèi)叫java.lang.System烟逊?

通常不可以渣窜,但可以采取另類(lèi)方法達(dá)到這個(gè)需求。為了不讓我們寫(xiě)System類(lèi)宪躯,類(lèi)加載采用委托機(jī)制乔宿,這樣可以保證爸爸們優(yōu)先,爸爸們能找到的類(lèi)访雪,兒子就沒(méi)有機(jī)會(huì)加載详瑞。而System類(lèi)是Bootstrap加載器加載的,就算自己重寫(xiě)臣缀,也總是使用Java系統(tǒng)提供的System坝橡,自己寫(xiě)的System類(lèi)根本沒(méi)有機(jī)會(huì)得到加載。但是精置,我們可以自己定義一個(gè)類(lèi)加載器來(lái)達(dá)到這個(gè)目的计寇,為了避免雙親委托機(jī)制,這個(gè)類(lèi)加載器也必須是特殊的脂倦。由于系統(tǒng)自帶的三個(gè)類(lèi)加載器都加載特定目錄下的類(lèi)番宁,如果我們自己的類(lèi)加載器放在一個(gè)特殊的目錄,那么系統(tǒng)的加載器就無(wú)法加載赖阻,也就是最終還是由我們自己的加載器加載蝶押。

4、如何自定義類(lèi)記載器火欧,代碼該怎么寫(xiě)棋电?

實(shí)現(xiàn)類(lèi)
測(cè)試類(lèi)

5茎截、類(lèi)加載器有些什么樣的應(yīng)用場(chǎng)景?為什么要使用類(lèi)加載器离陶?

資源隔離 熱部署 代碼保護(hù)

Java語(yǔ)言里稼虎,類(lèi)加載都是在程序運(yùn)行期間完成的,這種策略雖然會(huì)令類(lèi)加載時(shí)稍微增加一些性能開(kāi)銷(xiāo)招刨,但是會(huì)給java應(yīng)用程序提供高度的靈活性。例如:

a. 編寫(xiě)一個(gè)面向接口的應(yīng)用程序哀军,可能等到運(yùn)行時(shí)再指定其實(shí)現(xiàn)的子類(lèi)沉眶;

b. 用戶(hù)可以自定義一個(gè)類(lèi)加載器,讓程序在運(yùn)行時(shí)從網(wǎng)絡(luò)或其他地方加載一個(gè)二進(jìn)制流作為程序代碼的一部分杉适;(這個(gè)是Android插件化谎倔,動(dòng)態(tài)安裝更新apk的基礎(chǔ))

6、Class.forName()和ClassLoader.loadClass()區(qū)別

Class.forName():將類(lèi)的.class文件加載到j(luò)vm中之外猿推,還會(huì)對(duì)類(lèi)進(jìn)行解釋?zhuān)瑘?zhí)行類(lèi)中的static塊片习;

ClassLoader.loadClass():只干一件事情,就是將.class文件加載到j(luò)vm中蹬叭,不會(huì)執(zhí)行static中的內(nèi)容,只有在newInstance才會(huì)去執(zhí)行static塊藕咏。

:Class.forName(name, initialize, loader)帶參函數(shù)也可控制是否加載static塊。并且只有調(diào)用了newInstance()方法采用調(diào)用構(gòu)造函數(shù)秽五,創(chuàng)建類(lèi)的對(duì)象 孽查。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市坦喘,隨后出現(xiàn)的幾起案子盲再,更是在濱河造成了極大的恐慌,老刑警劉巖瓣铣,帶你破解...
    沈念sama閱讀 217,406評(píng)論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件答朋,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡棠笑,警方通過(guò)查閱死者的電腦和手機(jī)梦碗,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,732評(píng)論 3 393
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)腐晾,“玉大人叉弦,你說(shuō)我怎么就攤上這事≡逄牵” “怎么了淹冰?”我有些...
    開(kāi)封第一講書(shū)人閱讀 163,711評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)巨柒。 經(jīng)常有香客問(wèn)我樱拴,道長(zhǎng)柠衍,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,380評(píng)論 1 293
  • 正文 為了忘掉前任晶乔,我火速辦了婚禮珍坊,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘正罢。我一直安慰自己阵漏,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,432評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布翻具。 她就那樣靜靜地躺著履怯,像睡著了一般。 火紅的嫁衣襯著肌膚如雪裆泳。 梳的紋絲不亂的頭發(fā)上叹洲,一...
    開(kāi)封第一講書(shū)人閱讀 51,301評(píng)論 1 301
  • 那天,我揣著相機(jī)與錄音工禾,去河邊找鬼运提。 笑死,一個(gè)胖子當(dāng)著我的面吹牛闻葵,可吹牛的內(nèi)容都是我干的民泵。 我是一名探鬼主播,決...
    沈念sama閱讀 40,145評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼笙隙,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼洪灯!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起竟痰,我...
    開(kāi)封第一講書(shū)人閱讀 39,008評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤签钩,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后坏快,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體铅檩,經(jīng)...
    沈念sama閱讀 45,443評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,649評(píng)論 3 334
  • 正文 我和宋清朗相戀三年莽鸿,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了昧旨。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,795評(píng)論 1 347
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡祥得,死狀恐怖兔沃,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情级及,我是刑警寧澤乒疏,帶...
    沈念sama閱讀 35,501評(píng)論 5 345
  • 正文 年R本政府宣布,位于F島的核電站饮焦,受9級(jí)特大地震影響怕吴,放射性物質(zhì)發(fā)生泄漏窍侧。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,119評(píng)論 3 328
  • 文/蒙蒙 一转绷、第九天 我趴在偏房一處隱蔽的房頂上張望伟件。 院中可真熱鬧,春花似錦议经、人聲如沸斧账。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,731評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)其骄。三九已至,卻和暖如春扯旷,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背索抓。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,865評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工钧忽, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人逼肯。 一個(gè)月前我還...
    沈念sama閱讀 47,899評(píng)論 2 370
  • 正文 我出身青樓耸黑,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親篮幢。 傳聞我的和親對(duì)象是個(gè)殘疾皇子大刊,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,724評(píng)論 2 354

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