ClassLoader簡介

1.什么是Classloader

我們知道,我們寫的java程序會被編譯器編譯成class文件運行在jvm虛擬機上的固棚,Classloader就是jvm加載class文件的工具藏澳。

當我們new ClassName()仁锯,或者使用Class.forName("包路徑+類名"),或者使用classloader.loadclass("包路徑+類名")的時候翔悠,就會觸發(fā)Classloader去類加載對應(yīng)的路徑去查找*.class,并創(chuàng)建對象业崖。

正常情況下, 一個classLoader需要兩個必要屬性:
parent: 用于指明當前classLoader的父類加載器.
url: 類命名空間, 用于指明當前classLoader從哪里加載class文件.

2.Classloader的分類

2.1 BootstrapClassloader 啟動類加載器

其實類加載器也是java類,也需要被加載蓄愁。BootstrapClassloader就是最初加載Classloader的加載器双炕。而BootstrapClassloader本身,是JVM啟動時自動加載撮抓,是被C++啟動的妇斤。
BootstrapClassloader 負責加載JDK中的核心類庫,主要是JAVA_HOME/lib下的類丹拯,如rt.jar站超、resources.jar、charsets.jar等乖酬,這里包括其他的java自帶的類加載器死相。

2.2 ExtClassloader 擴展類加載器

主要負責加載Java的擴展類庫,默認加載JAVA_HOME/jre/lib/ext/目下的所有jar包剑刑。

2.3 AppClassloader 應(yīng)用類加載器

主要負責加載classpath下的類,這里包括用戶自己定義的類以及jar包双肤。

2.4 自定義的類加載器

繼承Classloader類實現(xiàn)自己的類加載器施掏,默認父加載器AppClassloader。
這里的父加載器茅糜,并不是繼承關(guān)系

3.Classloader的雙親委派

3.1什么是雙親委派

當一個類需要被加載時七芭,當前的類加載器會把加載任務(wù)委派給parent加載器,parent加載器又會把加載任務(wù)委派給自己parent加載器蔑赘,以此類推狸驳,
直到最頂層bootStrapClassLoader為止, 如果bootStrapClassLoader在自己的類空間(可以理解成上面提到的url)找到了該類的class文件, 就會去加載該類到內(nèi)存中. 如果找不到, 會把任務(wù)再向下傳遞回extClassLoader, 讓它去嘗試加載該類. 依次類推, 直到某個類加載器在自己的類命名空間里找到了該類的class文件, 就會把該類加載進內(nèi)存。


classLoader
3.2雙親委派機制的用處

雙親委派機制其實是java的一種安全機制缩赛,能保證類在內(nèi)存中只存在一份耙箍,所有程序使用的都是這一份, 不會出現(xiàn)自己定義一個String類, 被自己定義的classLoader給加載進來的情況, 因為rt.jar中的String會被最優(yōu)先加載.

4.自定義Classloader

4.1實現(xiàn)方式

繼承Classloader類,然后重寫findClass方法酥馍,方法內(nèi)去對應(yīng)的路徑下查找class文件辩昆,最后io讀入,用defineClass把byte[] 轉(zhuǎn)化為class對象旨袒。

import java.io.ByteArrayOutputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;

public class DqClassLoader extends ClassLoader {

    private String rootUrl;

    public DqClassLoader(String rootPath) {
        this.rootUrl = rootPath;
    }

    @Override
    protected Class<?> findClass(String name) throws ClassNotFoundException {
        Class clazz = null;
        //根據(jù)類的二進制名稱,獲得該class文件的字節(jié)碼數(shù)組
        byte[] classData = getClassData(name);
        if (classData == null) {
            throw new ClassNotFoundException();
        }
        //將class的字節(jié)碼數(shù)組轉(zhuǎn)換成Class類的實例
        clazz = defineClass(name, classData, 0, classData.length);
        return clazz;
    }

    private byte[] getClassData(String name) {
        InputStream is = null;
        try {
            String path = classNameToPath(name);
            is = new FileInputStream(path);
            byte[] buff = new byte[1024 * 4];
            int len = -1;
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            while ((len = is.read(buff)) != -1) {
                baos.write(buff, 0, len);
            }
            return baos.toByteArray();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (is != null) {
                try {
                    is.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return null;
    }

    private String classNameToPath(String name) {
        return rootUrl + "/" + name.replace(".", "/") + ".class";
    }
}
4.2 自定義加載器的應(yīng)用場景

最常見的應(yīng)用就是 Apache Tomcat 中的WebClassLoader汁针,每個 Web 應(yīng)用都有一個對應(yīng)的類加載器實例术辐。所不同的是它是首先嘗試去加載某個類,如果找不到再代理給父類加載器施无。這與一般類加載器的順序是相反的辉词。其目的是使得 Web 應(yīng)用自己的類的優(yōu)先級高于 Web 容器提供的類。
當然猾骡,Java 核心庫的類是不在查找范圍之內(nèi)的瑞躺。這也是為了保證 Java 核心庫的類型安全。

5.結(jié)尾

類加載器是 Java 語言的一個創(chuàng)新卓练。它使得動態(tài)安裝和更新軟件組件成為可能隘蝎。
在開發(fā)自己的類加載器的時候,需要注意與已有的類加載器組織結(jié)構(gòu)的協(xié)調(diào)襟企。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末嘱么,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子顽悼,更是在濱河造成了極大的恐慌曼振,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,591評論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件蔚龙,死亡現(xiàn)場離奇詭異冰评,居然都是意外死亡,警方通過查閱死者的電腦和手機木羹,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,448評論 3 392
  • 文/潘曉璐 我一進店門甲雅,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人坑填,你說我怎么就攤上這事抛人。” “怎么了脐瑰?”我有些...
    開封第一講書人閱讀 162,823評論 0 353
  • 文/不壞的土叔 我叫張陵妖枚,是天一觀的道長。 經(jīng)常有香客問我苍在,道長绝页,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,204評論 1 292
  • 正文 為了忘掉前任寂恬,我火速辦了婚禮续誉,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘初肉。我一直安慰自己屈芜,他們只是感情好,可當我...
    茶點故事閱讀 67,228評論 6 388
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著井佑,像睡著了一般属铁。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上躬翁,一...
    開封第一講書人閱讀 51,190評論 1 299
  • 那天焦蘑,我揣著相機與錄音,去河邊找鬼盒发。 笑死例嘱,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的宁舰。 我是一名探鬼主播拼卵,決...
    沈念sama閱讀 40,078評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼蛮艰!你這毒婦竟也來了腋腮?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,923評論 0 274
  • 序言:老撾萬榮一對情侶失蹤壤蚜,失蹤者是張志新(化名)和其女友劉穎即寡,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體袜刷,經(jīng)...
    沈念sama閱讀 45,334評論 1 310
  • 正文 獨居荒郊野嶺守林人離奇死亡聪富,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,550評論 2 333
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了著蟹。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片墩蔓。...
    茶點故事閱讀 39,727評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖萧豆,靈堂內(nèi)的尸體忽然破棺而出奸披,到底是詐尸還是另有隱情,我是刑警寧澤炕横,帶...
    沈念sama閱讀 35,428評論 5 343
  • 正文 年R本政府宣布源内,位于F島的核電站葡粒,受9級特大地震影響份殿,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜嗽交,卻給世界環(huán)境...
    茶點故事閱讀 41,022評論 3 326
  • 文/蒙蒙 一卿嘲、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧夫壁,春花似錦拾枣、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,672評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽司蔬。三九已至,卻和暖如春姨蝴,著一層夾襖步出監(jiān)牢的瞬間俊啼,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,826評論 1 269
  • 我被黑心中介騙來泰國打工左医, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留授帕,地道東北人。 一個月前我還...
    沈念sama閱讀 47,734評論 2 368
  • 正文 我出身青樓浮梢,卻偏偏與公主長得像跛十,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子秕硝,可洞房花燭夜當晚...
    茶點故事閱讀 44,619評論 2 354

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