JVM類加載機(jī)制

一 類加載過(guò)程

類加載:類加載器將class文件加載到j(luò)vm內(nèi)存中

image.png

(1) 加載:從磁盤查找并在找到后通過(guò)IO讀入字節(jié)碼文件
(2)建立連接做如下工作:
驗(yàn)證:驗(yàn)證字節(jié)碼文件內(nèi)容是否正確,有相應(yīng)的語(yǔ)法邏輯
準(zhǔn)備:給類的靜態(tài)變量分配內(nèi)存,并賦予java虛擬機(jī)規(guī)定的默認(rèn)值仗颈,比如 static int a=5丐巫,會(huì)賦予默認(rèn)值int a=0
解析:類加載器將類所引用的其他類裝載
(3)初始化:對(duì)類的靜態(tài)變量初始化為用戶代碼中指定的值,比如static int a=5知允,在這一步賦予值5

二 類加載器分類

JVM角度:

  1. 啟動(dòng)類加載器(bootstrap ClassLoader),該加載器使用C++實(shí)現(xiàn),是虛擬機(jī)自身一部分
  2. 其他所有的類加載器忽肛,這些加載器都由java實(shí)現(xiàn),獨(dú)立于JVM烂斋,全部繼承自java.lang.ClassLoader

開(kāi)發(fā)人員角度:

  1. 啟動(dòng)類加載器(Bootstrap ClassLoader)
  2. 擴(kuò)展類加載器(Extension ClassLoader)
  3. 應(yīng)用程序類加載器(Application ClassLoader)

應(yīng)用程序由著三種類加載器互相配合完成加載屹逛,三者關(guān)系如下圖


image.png

圖中的自定義加載器在我們自己寫程序的時(shí)候基本不會(huì)用到础废,一般如tomcat之類的中間件會(huì)使用到自定義類加載器

我們通過(guò)程序來(lái)看一下這幾種加載器

public class Test2 {
    public static void main(String[] args) {
        System.out.println(String.class.getClassLoader());
        System.out.println(com.sun.crypto.provider.DESKeyFactory.class.getClassLoader().getClass().getName());
        System.out.println(Test2.class.getClassLoader().getClass().getName());
// 系統(tǒng)類加載器就是應(yīng)用程序類加載器,通過(guò)上面一行代碼和下面一行代碼均可以打印
        System.out.println(ClassLoader.getSystemClassLoader().getClass().getName());
    }
}
image.png
image.png

之所以第一個(gè)string的類加載器沒(méi)有打印結(jié)果是因?yàn)榧逶矗瑂tring屬于rt.jar色迂,而rt.jar中含有jdk中最核心的類,是c和c++語(yǔ)言寫的手销,因此根本就不會(huì)知道他的名字

三 類加載機(jī)制

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

當(dāng)一個(gè)加載器加載了類A歇僧,則類A所依賴和引用的類比如類B和類C都將由加載類A的加載器加載

3.2 雙親委派機(jī)制

上圖中類加載器之間的層次關(guān)系,就叫做類加載器的雙親委派模型(parents delegation model)锋拖。雙親委派機(jī)制于jdk1.2引入诈悍。特點(diǎn)是除了頂層的啟動(dòng)類加載器外,其他的類加載器都應(yīng)當(dāng)有自己的父類加載器

父類加載器不是說(shuō)子類加載器繼承了父類加載器兽埃,而是子類加載器持有父類加載器的引用侥钳,可以通過(guò)這個(gè)引用找到父類加載器

3.2.1 雙親委派機(jī)制加載過(guò)程

如果一個(gè)類加載器收到類加載的請(qǐng)求,他首先不會(huì)去自己嘗試加載這個(gè)類柄错,而是將這個(gè)請(qǐng)求委派給自己的父類加載器完成舷夺,每個(gè)層次的類加載器都是這樣,因此所有的加載請(qǐng)求最后都會(huì)傳送給頂層的啟動(dòng)類加載器售貌,只有當(dāng)父類加載器反饋?zhàn)约簾o(wú)法完成這個(gè)加載請(qǐng)求(他的搜索范圍沒(méi)有找到所需的類)時(shí)候给猾,子加載器才會(huì)嘗試去加載

比如加載我們自己寫的類A.class,類A中引用了我們自己寫的java.lang.string.class颂跨,則應(yīng)用程序加載器在加載類A的時(shí)候敢伸,會(huì)順便嘗試加載我們自己寫的string.class,加載的話不是直接加載而是委托給父類加載器一級(jí)一級(jí)上去直到啟動(dòng)類加載器加載到正確的string.class

測(cè)試案例:

package java.lang;

public class String {

    public static void main(String[] args) {
        System.out.println("hello world");
    }
}
image.png

可以看到程序沒(méi)有打印這句話恒削,因?yàn)椴](méi)有加載我們自己的string.class而是加載了jdk自己的string.class池颈,實(shí)際運(yùn)行的是jdk的string類,jdk的string類是沒(méi)有main方法的因此報(bào)錯(cuò)

3.2.2 雙親委派機(jī)制優(yōu)點(diǎn)

  • 沙箱安全機(jī)制:
    自己寫的java.lang.string.class類不會(huì)被加載钓丰,這樣可以防止jdk核心rt.jar中類被隨意篡改
    因?yàn)榧?/li>
  • 避免類的重復(fù)加載
    當(dāng)父類已經(jīng)加載了該類以后躯砰,子類加載器將不再加載該類

四 JVM加載jar包是否將jar包中所有類加載到內(nèi)存

jvm對(duì)class文件的加載是按需加載,不會(huì)一次性加載

代碼示例:
下面代碼執(zhí)行的時(shí)候携丁,需要在執(zhí)行前添加執(zhí)行參數(shù): -verbose:class 弃揽,加上以后除了打印正常輸出之外,還會(huì)打印jvm中類加載相關(guān)的信息


image.png
public class TestDynamicLoad {

    static {
        System.out.println("*************static code************");
    }

    public static void main(String[] args){
        new A();
        System.out.println("*************load test************");
        new B();
    }
}

class A{
    public A(){
        System.out.println("*************initial A************");
    }
}

class B{
    public B(){
        System.out.println("*************initial B************");
    }
}
image.png

從上面的運(yùn)行結(jié)果可以看到则北,由之前學(xué)到的靜態(tài)代碼塊是在類初始化的時(shí)候執(zhí)行的矿微,這個(gè)時(shí)候已經(jīng)完成了類加載,因此我們?cè)谇懊婵梢钥吹疆?dāng)前類被加載的信息尚揣,但是當(dāng)前類應(yīng)用的類A和類B并未在開(kāi)始的時(shí)候就加載涌矢,而是在用到了以后才加載

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市快骗,隨后出現(xiàn)的幾起案子娜庇,更是在濱河造成了極大的恐慌塔次,老刑警劉巖,帶你破解...
    沈念sama閱讀 212,599評(píng)論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件名秀,死亡現(xiàn)場(chǎng)離奇詭異励负,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)匕得,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,629評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門继榆,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人汁掠,你說(shuō)我怎么就攤上這事略吨。” “怎么了考阱?”我有些...
    開(kāi)封第一講書(shū)人閱讀 158,084評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵翠忠,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我乞榨,道長(zhǎng)秽之,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 56,708評(píng)論 1 284
  • 正文 為了忘掉前任吃既,我火速辦了婚禮政溃,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘态秧。我一直安慰自己,他們只是感情好扼鞋,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,813評(píng)論 6 386
  • 文/花漫 我一把揭開(kāi)白布申鱼。 她就那樣靜靜地躺著,像睡著了一般云头。 火紅的嫁衣襯著肌膚如雪捐友。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 50,021評(píng)論 1 291
  • 那天溃槐,我揣著相機(jī)與錄音匣砖,去河邊找鬼。 笑死昏滴,一個(gè)胖子當(dāng)著我的面吹牛猴鲫,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播谣殊,決...
    沈念sama閱讀 39,120評(píng)論 3 410
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼拂共,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了姻几?” 一聲冷哼從身側(cè)響起宜狐,我...
    開(kāi)封第一講書(shū)人閱讀 37,866評(píng)論 0 268
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤势告,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后抚恒,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體咱台,經(jīng)...
    沈念sama閱讀 44,308評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,633評(píng)論 2 327
  • 正文 我和宋清朗相戀三年俭驮,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了回溺。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,768評(píng)論 1 341
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡表鳍,死狀恐怖馅而,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情譬圣,我是刑警寧澤瓮恭,帶...
    沈念sama閱讀 34,461評(píng)論 4 333
  • 正文 年R本政府宣布,位于F島的核電站厘熟,受9級(jí)特大地震影響屯蹦,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜绳姨,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 40,094評(píng)論 3 317
  • 文/蒙蒙 一登澜、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧飘庄,春花似錦脑蠕、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,850評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至碾盐,卻和暖如春晃跺,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背毫玖。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,082評(píng)論 1 267
  • 我被黑心中介騙來(lái)泰國(guó)打工掀虎, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人付枫。 一個(gè)月前我還...
    沈念sama閱讀 46,571評(píng)論 2 362
  • 正文 我出身青樓烹玉,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親阐滩。 傳聞我的和親對(duì)象是個(gè)殘疾皇子春霍,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,666評(píng)論 2 350