類加載器

簡(jiǎn)介

Java類加載器是Java運(yùn)行時(shí)環(huán)境(Java Runtime Environment)的一部分,負(fù)責(zé)動(dòng)態(tài)加載Java類到Java虛擬機(jī)的內(nèi)存空間中近弟。類通常是按需加載缅糟,即第一次使用該類時(shí)才加載。 由于有了類加載器祷愉,Java運(yùn)行時(shí)系統(tǒng)不需要知道文件與文件系統(tǒng)窗宦。每個(gè)Java類必須由某個(gè)類加載器裝入到內(nèi)存。

類裝載器子系統(tǒng)涉及Java虛擬機(jī)的其他幾個(gè)組成部分二鳄,以及幾個(gè)來(lái)自java.lang庫(kù)的類赴涵。比如,用戶自定義的類裝載器只是普通的Java對(duì)象订讼,它的類必須派生自java.lang.ClassLoader髓窜。ClassLoader中定義的方法為程序提供了訪問(wèn)類裝載器機(jī)制的接口。此外欺殿,對(duì)于每個(gè)被裝載的類型寄纵,Java虛擬機(jī)都會(huì)為他創(chuàng)建一個(gè)java.lang.Class類的實(shí)例來(lái)代表該類型。和所有其他對(duì)象一樣脖苏,用戶自定義的類裝載器以及Class類的實(shí)例都放在內(nèi)存中的堆區(qū)程拭,而裝載的類型信息都位于方法區(qū)。

類裝載器子系統(tǒng)除了要定位和導(dǎo)入二進(jìn)制class文件外棍潘,還必須負(fù)責(zé)驗(yàn)證被導(dǎo)入類的正確性恃鞋,為變量分配初始化內(nèi)存,以及幫助解析符號(hào)引用亦歉。這些動(dòng)作必須嚴(yán)格按一下順序完成:

  1. 裝載--查找并裝載類型的二進(jìn)制數(shù)據(jù)恤浪。
  2. 鏈接--執(zhí)行驗(yàn)證、準(zhǔn)備以及解析(可選)
- 驗(yàn)證  確保被導(dǎo)入類型的正確性
- 準(zhǔn)備  為類變量分配內(nèi)存肴楷,并將其初始化為默認(rèn)值水由。
- 解析  把類型中的符號(hào)引用轉(zhuǎn)換為直接引用。
  1. 初始化--把類變量初始化為正確的初始值赛蔫。

分類

在Java虛擬機(jī)中存在多個(gè)類裝載器绷杜,Java應(yīng)用程序可以使用兩種類裝載器:

  • 啟動(dòng)(bootstrap)類裝載器:此裝載器是Java虛擬機(jī)實(shí)現(xiàn)的一部分。由原生代碼(如C語(yǔ)言)編寫濒募,不繼承自java.lang.ClassLoader。負(fù)責(zé)加載核心Java庫(kù)圾结,存儲(chǔ)在<JAVA_HOME>/jre/lib目錄中瑰剃。(如果Java虛擬機(jī)在已有操作系統(tǒng)中實(shí)現(xiàn)為C程序,那么啟動(dòng)類加載器就是此C程序的一部分) 啟動(dòng)類裝載器通常使用某種默認(rèn)的方式從本地磁盤中加載類筝野,包括Java API晌姚。

  • 用戶自定義類裝載器(包含但不止粤剧,擴(kuò)展類加載器以及系統(tǒng)類加載器) ,繼承自Java中的java.lang.ClassLoader類挥唠,Java應(yīng)用程序能在運(yùn)行時(shí)安裝用戶自定義類裝載器抵恋,這種累裝載器使用自定義的方式來(lái)裝載類。用戶定義的類裝載器能用Java編寫宝磨,能夠被編譯為Class文件弧关,能被虛擬機(jī)裝載,還能像其他對(duì)象一樣實(shí)例化唤锉。它們實(shí)際上只是運(yùn)行中的Java程序可執(zhí)行代碼的一部分世囊。一般JVM都會(huì)提供一些基本實(shí)現(xiàn)。應(yīng)用程序的開(kāi)發(fā)人員也可以根據(jù)需要編寫自己的類加載器窿祥。JVM中最常使用的是系統(tǒng)類加載器(system)株憾,它用來(lái)啟動(dòng)Java應(yīng)用程序的加載。 通過(guò)java.lang.ClassLoader.getSystemClassLoader() 可以獲取到該類加載器對(duì)象晒衩。該類由sun.misc.Launcher$AppClassLoader實(shí)現(xiàn)嗤瞎。

java-class-loader.png

全盤負(fù)責(zé)雙親委托機(jī)制

全盤負(fù)責(zé)是指當(dāng)一個(gè)ClassLoader裝載一個(gè)類的時(shí),除非顯式地使用另一個(gè)ClassLoader听系,該類所依賴及引用的類也由這個(gè)ClassLoader載入贝奇;“雙親委托機(jī)制”是指先委托父裝載器尋找目標(biāo)類,只有在找不到的情況下才從自己的類路徑中查找并裝載目標(biāo)類跛锌。這一點(diǎn)是從安全角度考慮的弃秆,試想如果有人編寫了一個(gè)惡意的基礎(chǔ)類(如java.lang.String)并裝載到JVM中將會(huì)引起多么可怕的后果。但是由于有了“全盤負(fù)責(zé)委托機(jī)制”髓帽,java.lang.String永遠(yuǎn)是由根裝載器來(lái)裝載的菠赚,這樣就避免了上述事件的發(fā)生。

類加載器需要完成的最終功能是定義一個(gè)Java類郑藏,即把Java字節(jié)代碼轉(zhuǎn)換成JVM中的java.lang.Class類的對(duì)象衡查。但是類加載的過(guò)程并不是這么簡(jiǎn)單追驴。Java類加載器有兩個(gè)比較重要的特征:

  • 層次組織結(jié)構(gòu)指的是每個(gè)類加載器都有一個(gè)父類加載器假抄,通過(guò)getParent()方法可以獲取到。類加載器通過(guò)這種父親-后代的方式組織在一起撮珠,形成樹狀層次結(jié)構(gòu)歌粥。

  • 代理模式則指的是一個(gè)類加載器既可以自己完成Java類的定義工作塌忽,也可以代理給其它的類加載器來(lái)完成。由于代理模式的存在失驶,啟動(dòng)一個(gè)類的加載過(guò)程的類加載器和最終定義這個(gè)類的類加載器可能并不是一個(gè)土居。前者稱為初始類加載器,而后者稱為定義類加載器。

兩者的關(guān)聯(lián)在于:在每個(gè)類被裝載的時(shí)候擦耀,Java虛擬機(jī)都會(huì)監(jiān)視這個(gè)類棉圈,看它到底是被啟動(dòng)類裝載器還是被用戶自定義類裝載器裝載。當(dāng)被裝載的類引用了另外一個(gè)類的時(shí)候眷蜓,虛擬機(jī)就會(huì)使用裝載第一個(gè)類的類裝載器裝載被引用的類分瘾。

注意:JVM加載類A,并使用A的ClassLoader去加載B吁系,但B的類加載器并不一定和A的類加載器一致德召,這是因?yàn)橛须p親委托機(jī)制的存在。

一般的類加載器在嘗試自己去加載某個(gè)Java類之前垮抗,會(huì) 首先代理給其父類加載器氏捞。當(dāng)父類加載器找不到的時(shí)候,才會(huì)嘗試自己加載冒版。這個(gè)邏輯是封裝在java.lang.ClassLoader類的loadClass()方法中的液茎。一般來(lái)說(shuō),父類優(yōu)先的策略就足夠好了辞嗡。在某些情況下捆等,可能需要采取相反的策略,即先嘗試自己加載续室,找不到的時(shí)候再代理給父類加載器栋烤。這種做法在Java的Web容器中比較常見(jiàn),也是Servlet規(guī)范推薦的做法挺狰。 比如明郭,Apache Tomcat為每個(gè)Web應(yīng)用都提供一個(gè)獨(dú)立的類加載器,使用的就是自己優(yōu)先加載的策略丰泊。IBM WebSphere Application Server則允許Web應(yīng)用選擇類加載器使用的策略薯定。

class-loader-proxy-partten.png

假設(shè) 類加載器B2被要求裝載類MyClass,在parent delegation模型下瞳购,類加載器B2首先請(qǐng)求類加載器B代為裝載话侄,類加載器B再請(qǐng)求系統(tǒng)類裝載器去裝載MyClass,系統(tǒng)類裝載器也會(huì)繼續(xù)請(qǐng)求它的Parent擴(kuò)展類加載器去裝載MyClass学赛,以此類推直到引導(dǎo)類裝載器年堆。若引導(dǎo)類裝載器能成功裝載,則將MyClass所對(duì)應(yīng)的Class對(duì)象的reference逐層返回到類加載器B2盏浇,若引導(dǎo)類裝載器不能成功裝載变丧,下層的擴(kuò)展類裝載器將嘗試裝載,并以此類推直到類裝載器B2如果也不能成功裝載绢掰,則裝載失敗锄贷。

需要指出的是译蒂,Class Loader是對(duì)象,它的父子關(guān)系和類的父子關(guān)系沒(méi)有任何關(guān)系谊却。一對(duì)父子loader可能實(shí)例化自同一個(gè) Class,也可能不是哑芹,甚至父loader實(shí)例化自子類炎辨,子loader實(shí)例化自父類。

運(yùn)行時(shí)包

類加載器的一個(gè)重要用途是 在JVM中為相同名稱的Java類創(chuàng)建隔離空間聪姿。在JVM中碴萧,判斷兩個(gè)類是否相同,不僅是根據(jù)該類的二進(jìn)制名稱末购,還需要根據(jù)兩個(gè)類的定義類加載器破喻。 只有兩者完全一樣,才認(rèn)為兩個(gè)類的是相同的盟榴。

在允許兩個(gè)類型之間對(duì)包內(nèi)可見(jiàn)的成員進(jìn)行訪問(wèn)前曹质,虛擬機(jī)不但要確定這個(gè)兩個(gè)類型屬于同一個(gè)包,還必須確認(rèn)它們屬于同一個(gè)運(yùn)行時(shí)包-它們必須有同一個(gè)類裝載器裝載的擎场。 這樣羽德,java.lang.Virus和來(lái)自核心的java.lang的類不屬于同一個(gè)運(yùn)行時(shí)包,java.lang.Virus就不能訪問(wèn)JAVA API的java.lang包中的包內(nèi)可見(jiàn)的成員迅办。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末宅静,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子站欺,更是在濱河造成了極大的恐慌姨夹,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,639評(píng)論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件矾策,死亡現(xiàn)場(chǎng)離奇詭異磷账,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)蝴韭,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,277評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門够颠,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人榄鉴,你說(shuō)我怎么就攤上這事履磨。” “怎么了庆尘?”我有些...
    開(kāi)封第一講書人閱讀 157,221評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵剃诅,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我驶忌,道長(zhǎng)矛辕,這世上最難降的妖魔是什么笑跛? 我笑而不...
    開(kāi)封第一講書人閱讀 56,474評(píng)論 1 283
  • 正文 為了忘掉前任,我火速辦了婚禮聊品,結(jié)果婚禮上飞蹂,老公的妹妹穿的比我還像新娘。我一直安慰自己翻屈,他們只是感情好陈哑,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,570評(píng)論 6 386
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著伸眶,像睡著了一般惊窖。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上厘贼,一...
    開(kāi)封第一講書人閱讀 49,816評(píng)論 1 290
  • 那天界酒,我揣著相機(jī)與錄音,去河邊找鬼嘴秸。 笑死毁欣,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的赁遗。 我是一名探鬼主播署辉,決...
    沈念sama閱讀 38,957評(píng)論 3 408
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼岩四!你這毒婦竟也來(lái)了哭尝?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書人閱讀 37,718評(píng)論 0 266
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤剖煌,失蹤者是張志新(化名)和其女友劉穎材鹦,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體耕姊,經(jīng)...
    沈念sama閱讀 44,176評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡桶唐,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,511評(píng)論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了茉兰。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片尤泽。...
    茶點(diǎn)故事閱讀 38,646評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖规脸,靈堂內(nèi)的尸體忽然破棺而出坯约,到底是詐尸還是另有隱情,我是刑警寧澤莫鸭,帶...
    沈念sama閱讀 34,322評(píng)論 4 330
  • 正文 年R本政府宣布闹丐,位于F島的核電站,受9級(jí)特大地震影響被因,放射性物質(zhì)發(fā)生泄漏卿拴。R本人自食惡果不足惜衫仑,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,934評(píng)論 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望堕花。 院中可真熱鬧文狱,春花似錦、人聲如沸航徙。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 30,755評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)到踏。三九已至,卻和暖如春尚猿,著一層夾襖步出監(jiān)牢的瞬間窝稿,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 31,987評(píng)論 1 266
  • 我被黑心中介騙來(lái)泰國(guó)打工凿掂, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留伴榔,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 46,358評(píng)論 2 360
  • 正文 我出身青樓庄萎,卻偏偏與公主長(zhǎng)得像踪少,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子糠涛,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,514評(píng)論 2 348

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