Java 虛擬機(jī) | 類加載機(jī)制

點(diǎn)贊關(guān)注暴凑,不再迷路,你的支持對我意義重大娶桦!

?? Hi踱蠢,我是丑丑。本文 「Java 路線」| 導(dǎo)讀 —— 他山之石咪辱,可以攻玉 已收錄振劳,這里有 Android 進(jìn)階成長路線筆記 & 博客,歡迎跟著彭丑丑一起成長油狂。(聯(lián)系方式在 GitHub)

前言

  • 在 Java 中历恐,編譯產(chǎn)物 .class 是一個(gè)靜態(tài)的存儲(chǔ)結(jié)構(gòu),需要加載到內(nèi)存中的運(yùn)行時(shí)數(shù)據(jù)結(jié)構(gòu)专筷,才能為我們所用弱贼。Java 的類加載機(jī)制是很多技術(shù)的基礎(chǔ),同時(shí)也是面試的重點(diǎn)知識(shí)磷蛹,務(wù)必深刻理解吮旅。
  • 在這篇文章里,我將分析 Java 類加載機(jī)制的原理味咳,整個(gè)過程分為三個(gè)部分:類查找的委派模型 & 類加載的時(shí)機(jī) & 類加載的流程庇勃。如果能幫上忙,請務(wù)必點(diǎn)贊加關(guān)注槽驶,這真的對我非常重要责嚷。

目錄


1. 類加載的委派模型

1.1 類加載器 = 命名空間

類的唯一性由兩個(gè)因素決定:「類的全限定類名」+「類加載器」。類加載器相當(dāng)于類的命名空間掂铐,要判斷兩個(gè)類是否相同罕拂,除了判斷類名是否相同外揍异,還需要判斷是否由同一個(gè) ClassLoader 加載。

提示: 類的唯一性判斷會(huì)影響:Class#equals聂受、Class#isAssignableFrom()蒿秦、Class#isInstance()烤镐、instanceof 的判斷結(jié)果蛋济。

1.2 類加載的工作機(jī)制

Java 類加載是一種委托機(jī)制(parent delegate),即:除了頂級(jí)啟動(dòng)類加載器(bootstrap classloader)之外炮叶,每個(gè)類加載器都有一個(gè)關(guān)聯(lián)的上級(jí)類加載器(parent 字段)碗旅。當(dāng)一個(gè)類加載器準(zhǔn)備執(zhí)行類加載時(shí),它首先會(huì)委托給上級(jí)加載器去加載镜悉,而上級(jí)加載器可能還會(huì)繼續(xù)向上委托祟辟,遞歸這個(gè)過程。如果上級(jí)構(gòu)造器無法加載侣肄,才會(huì)返回由自己加載旧困。

ClassLoader.java

public abstract class ClassLoader {

    上級(jí)類加載器
    private final ClassLoader parent;

    protected Class<?> loadClass(String name, boolean resolve) {

        1、檢查是否加載過
        Class<?> c = findLoadedClass(name);

        if (c == null) {
            try {
                if (parent != null) {
                    2.1 遞歸委派給上級(jí)類加載器
                    c = parent.loadClass(name, false);
                } else {
                    2.2 委派給頂級(jí)啟動(dòng)類加載器
                    c = findBootstrapClassOrNull(name);
                }
            } catch (ClassNotFoundException e) {
                2.3 上級(jí)類加載器無法加載稼锅,拋出異常
            }

            3. 交給自己加載吼具,findClass() 我后文再說
            if (c == null) {
                c = findClass(name);
            }
        }
        return c;
    }
    
    protected Class<?> findClass(String name) throws ClassNotFoundException {
        throw new ClassNotFoundException(name);
    }
}

提示: 只有 bootstrap classloader 的 parent 字段為空。

1.3 “雙親” 委派是不好的翻譯

在很多資料里會(huì)提到 “雙親委派機(jī)制” 的概念矩距,這其實(shí)是不信達(dá)雅的翻譯了拗盒。 “雙親” 原文是 parent delegate,在 Java 文檔原文的意思:將加載類的任務(wù)委派給上一級(jí)類加載器锥债,而雙親的翻譯卻讓人摸不著頭腦陡蝇。

《The Java? Tutorials》

The Java platform uses a delegation model for loading classes. The basic idea is that every class loader has a "parent" class loader. When loading a class, a class loader first "delegates" the search for the class to its parent class loader before attempting to find the class itself.

1.4 優(yōu)點(diǎn)

  • 1、復(fù)用: 使用上級(jí)類加載器加載過的類哮肚,避免重復(fù)加載登夫;
  • 2、安全(基礎(chǔ)類型的一致性): 防止加載被篡改的基礎(chǔ)類 .class文件允趟。

1.5 破壞委派模型

  • 1恼策、兼容jdk1.2,loadclass不禁止重寫
  • 2拼窥、Bootstrap ClassLoader加載用戶類(解決方案:Thread Context ClassLoader)

2. Java 中的類加載器

筆者是 Android 黨戏蔑,這部分內(nèi)容不熟悉,有緣再見鲁纠。如果你對 Android 中的類加載器感興趣总棵,可以看下同系列的這篇文章:「Android 路線」插件化的基本原理

3. 自定義的類加載器

Editting...


4. 類加載的時(shí)機(jī)

Editting...


5. 類加載的流程

5.1 概述

在類加載階段,虛擬機(jī)主要完成三件事情:

  • 1改含、通過「類的全限定類名」來加載 「.class 文件的二進(jìn)制字節(jié)流」情龄;
  • 2、將「.class 字節(jié)流」轉(zhuǎn)換為「類的運(yùn)行時(shí)數(shù)據(jù)結(jié)構(gòu)」(存儲(chǔ)在方法區(qū));
  • 3骤视、在 Java 堆中生成一個(gè)「類的 Class 對象」鞍爱,它將作為方法區(qū)類數(shù)據(jù)的訪問入口。

其中第 2 步专酗,將 .class 字節(jié)流轉(zhuǎn)換為類的運(yùn)行時(shí)數(shù)據(jù)結(jié)構(gòu)的步驟睹逃,具體分為:

  • 1.加載:獲取類的二進(jìn)制字節(jié)流;生成方法區(qū)的運(yùn)行時(shí)存儲(chǔ)結(jié)構(gòu)祷肯;在內(nèi)存中生成 Class 對象 2.驗(yàn)證:確保該 Class 字節(jié)流符合虛擬機(jī)要求 3.準(zhǔn)備:初始化靜態(tài)變量 4.解析:將常量池的符號(hào)引用替換為直接引用 5.初始化:執(zhí)行靜態(tài)塊代碼沉填、類變量賦值

Editting...


6. so 庫加載流程

除了加載類,ClassLoader 還需要負(fù)責(zé)加載 so 庫佑笋,這個(gè)問題在我之前寫過的一篇文章里分析過了:「NDK 路線」| so 庫加載到卸載的全過程翼闹。


7. 總結(jié)

Editting...


參考資料


創(chuàng)作不易蒋纬,你的「三連」是丑丑最大的動(dòng)力猎荠,我們下次見!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末蜀备,一起剝皮案震驚了整個(gè)濱河市关摇,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌琼掠,老刑警劉巖拒垃,帶你破解...
    沈念sama閱讀 211,265評(píng)論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異瓷蛙,居然都是意外死亡悼瓮,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,078評(píng)論 2 385
  • 文/潘曉璐 我一進(jìn)店門艰猬,熙熙樓的掌柜王于貴愁眉苦臉地迎上來横堡,“玉大人,你說我怎么就攤上這事冠桃∶” “怎么了?”我有些...
    開封第一講書人閱讀 156,852評(píng)論 0 347
  • 文/不壞的土叔 我叫張陵食听,是天一觀的道長胸蛛。 經(jīng)常有香客問我,道長樱报,這世上最難降的妖魔是什么葬项? 我笑而不...
    開封第一講書人閱讀 56,408評(píng)論 1 283
  • 正文 為了忘掉前任,我火速辦了婚禮迹蛤,結(jié)果婚禮上民珍,老公的妹妹穿的比我還像新娘襟士。我一直安慰自己,他們只是感情好嚷量,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,445評(píng)論 5 384
  • 文/花漫 我一把揭開白布陋桂。 她就那樣靜靜地躺著,像睡著了一般蝶溶。 火紅的嫁衣襯著肌膚如雪嗜历。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,772評(píng)論 1 290
  • 那天身坐,我揣著相機(jī)與錄音秸脱,去河邊找鬼落包。 笑死部蛇,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的咐蝇。 我是一名探鬼主播涯鲁,決...
    沈念sama閱讀 38,921評(píng)論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼有序!你這毒婦竟也來了抹腿?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,688評(píng)論 0 266
  • 序言:老撾萬榮一對情侶失蹤旭寿,失蹤者是張志新(化名)和其女友劉穎警绩,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體盅称,經(jīng)...
    沈念sama閱讀 44,130評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡肩祥,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,467評(píng)論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了缩膝。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片混狠。...
    茶點(diǎn)故事閱讀 38,617評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖疾层,靈堂內(nèi)的尸體忽然破棺而出将饺,到底是詐尸還是另有隱情,我是刑警寧澤痛黎,帶...
    沈念sama閱讀 34,276評(píng)論 4 329
  • 正文 年R本政府宣布予弧,位于F島的核電站,受9級(jí)特大地震影響湖饱,放射性物質(zhì)發(fā)生泄漏掖蛤。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,882評(píng)論 3 312
  • 文/蒙蒙 一琉历、第九天 我趴在偏房一處隱蔽的房頂上張望坠七。 院中可真熱鬧水醋,春花似錦、人聲如沸彪置。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,740評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽拳魁。三九已至惶桐,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間潘懊,已是汗流浹背姚糊。 一陣腳步聲響...
    開封第一講書人閱讀 31,967評(píng)論 1 265
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留授舟,地道東北人救恨。 一個(gè)月前我還...
    沈念sama閱讀 46,315評(píng)論 2 360
  • 正文 我出身青樓,卻偏偏與公主長得像释树,于是被迫代替她去往敵國和親肠槽。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,486評(píng)論 2 348

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