Tomcat類(lèi)載入器

? ? ? ?大家都知道俊嗽,Java的類(lèi)加載機(jī)制是雙親委派模型墨辛,那么什么是雙親委派模型呢瘪吏?我們這里簡(jiǎn)要的說(shuō)一下鞍历,雙親委派模型就是說(shuō)把類(lèi)的加載委托給它的父類(lèi)加載器去加載,父加載器委托給它的祖父加載器去加載肪虎,一直這樣,直到它的父加載器是null為止惧蛹,類(lèi)加載器有如下的幾種類(lèi)型:

image.jpeg

類(lèi)加載器的源代碼如下扇救,從中,我們可以很清楚的看到類(lèi)加載委派的過(guò)程:

protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException {
        synchronized (getClassLoadingLock(name)) {
            // First, check if the class has already been loaded
            Class<?> c = findLoadedClass(name);
            if (c == null) {
                long t0 = System.nanoTime();
                try {
                    //這里就是委派過(guò)程香嗓,直到父類(lèi)加載器為null為止
                    if (parent != null) {
                        c = parent.loadClass(name, false);
                    } else {
                        c = findBootstrapClassOrNull(name);
                    }
                } catch (ClassNotFoundException e) {
                // ClassNotFoundException thrown if class not found
                // from the non-null parent class loader
                }
                if (c == null) {
                    // If still not found, then invoke findClass in order
                    // to find the class.
                    long t1 = System.nanoTime();
                    c = findClass(name);
                    // this is the defining class loader; record the stats
                    sun.misc.PerfCounter.getParentDelegationTime().addTime(t1 - t0);
                    sun.misc.PerfCounter.getFindClassTime().addElapsedTimeFrom(t1);
                    sun.misc.PerfCounter.getFindClasses().increment();
                }
            }
            if (resolve) {
                resolveClass(c);
            }
            return c;
        }
    }

? ? ? ?好了迅腔,Java的類(lèi)加載機(jī)制就說(shuō)道這里,畢竟我們這里是看看tomcat的類(lèi)載入器靠娱,下面進(jìn)入主題沧烈。參考書(shū)籍(深入剖析tomcat)。
? ? ? ?tomcat必須實(shí)現(xiàn)一個(gè)自己的類(lèi)加載器像云,這是因?yàn)槲覀儾⒉荒芡耆湃蝧ervlet容器锌雀,他應(yīng)該只能加載自己WEB-INF/classes目錄下的類(lèi)和部署到WEB-INF/lib中的類(lèi)蚂夕,而在tomcat中,這個(gè)類(lèi)必須實(shí)現(xiàn)org.apache.catalina.Loader腋逆。先來(lái)看看Loader接口的定義:

public interface Loader {
        //這個(gè)方法在后面說(shuō)
        public void backgroundProcess();
        //獲取ClassLoader實(shí)例
        public ClassLoader getClassLoader();
        //獲取Context
        public Context getContext();

        public void setContext(Context context);

        public boolean getDelegate();
        //指明是否要委托給一個(gè)父類(lèi)加載器
        public void setDelegate(boolean delegate);

        public boolean getReloadable();

        public void setReloadable(boolean reloadable);

        public void addPropertyChangeListener(PropertyChangeListener listener);
        //獲取tomcat里的類(lèi)是否發(fā)生了修改

        public boolean modified();

        public void removePropertyChangeListener(PropertyChangeListener listener);

    }

? ? ? ?我們主要看modified()方法婿牍,這個(gè)方法是用來(lái)獲取tomcat里的類(lèi)是否發(fā)生了修改,我們都知道惩歉,我們可以通過(guò)配置來(lái)修改tomcat是否支持熱啟動(dòng)等脂,那么它的原理是什么呢?它通過(guò)一個(gè)線(xiàn)程來(lái)周期性的調(diào)用modified()方法撑蚌,來(lái)確定類(lèi)是否發(fā)生了修改上遥,如果發(fā)生了,那么就會(huì)調(diào)用context的reload方法來(lái)自動(dòng)重載争涌,我們可以去org.apache.catalina.core.ContainerBase類(lèi)中找到run()方法粉楚,其由內(nèi)部類(lèi)ContainerBackgroundProcessor實(shí)現(xiàn),它周期的調(diào)用org.apache.catalina.core.StandardContext下的backgroundProcess()方法第煮,而這個(gè)backgroundProcess 方法也是Loader接口中聲明的方法解幼,這個(gè)方法如下所示:

@Override
    public void backgroundProcess() {
        if (reloadable && modified()) {
            try {
                Thread.currentThread().setContextClassLoader(WebappLoader.class.getClassLoader());
                if (context != null) {
                    //發(fā)生了修改,這調(diào)用context的reload方法包警,重新加載容器
                    context.reload();
                }
            } finally {
                if (context != null && context.getLoader() != null) {
                    Thread.currentThread().setContextClassLoader(context.getLoader().getClassLoader());
                }
            }
        }
    }

? ? ? ?至此撵摆,可以看到tomcat是如何支持熱啟動(dòng)的。
? ? ? ?在tomcat中害晦,負(fù)責(zé)載入類(lèi)的是WebappClassLoader特铝,它的父類(lèi)中定義了一些不能載入的類(lèi),比如以javax開(kāi)頭的類(lèi)壹瘟,具體可以到WebappClassLoaderBase類(lèi)中的filter方法中查看鲫剿。當(dāng)然,為了達(dá)到更好的性能稻轨,會(huì)緩存已經(jīng)載入的類(lèi)灵莲,下次使用的時(shí)候就可以直接獲取。
? ? ? ?在載入類(lèi)的時(shí)候殴俱,WebappClassLoader會(huì)遵守如下的規(guī)則:
? ? ? ?1)因?yàn)樗幸呀?jīng)載入的類(lèi)都會(huì)緩存起來(lái)政冻,所以載入類(lèi)時(shí)要先檢查本地緩存;
? ? ? ?2)若本地緩存中沒(méi)有线欲,則檢查上一層緩存明场,即調(diào)用 java.lang.ClassLoader 類(lèi)的findLoadedClass() 方法;
? ? ? ?3)若兩個(gè)緩存中都沒(méi)有李丰,則使用系統(tǒng)的類(lèi)載入器進(jìn)行加載苦锨,防止 web 應(yīng)用程序中的類(lèi)覆蓋J2EE 的類(lèi);
? ? ? ?4)若啟用了 SecurityManager,則檢查是否允許載入該類(lèi)舟舒。若該類(lèi)是禁止載入的類(lèi)拉庶,拋出 ClassNotFoundException異常;
? ? ? ?5)若打開(kāi)標(biāo)志位 delegate魏蔗,或者待載入的類(lèi)是屬于包觸發(fā)器中的包名砍的,則調(diào)用父載入器來(lái)載入相關(guān)類(lèi)。如果父載入器是null莺治,則使用系統(tǒng)的類(lèi)載入器廓鞠;
? ? ? ?6)從當(dāng)前倉(cāng)庫(kù)中載入相關(guān)的類(lèi);
? ? ? ?7)若當(dāng)前倉(cāng)庫(kù)中沒(méi)有需要的類(lèi)谣旁,且標(biāo)志位delegate關(guān)閉床佳,則使用父類(lèi)載入器。若父類(lèi)載入器為 null榄审, 則使用系統(tǒng)的類(lèi)載入器進(jìn)行加載砌们;
? ? ? ?8)若仍未找到需要的類(lèi),則拋出 ClassNotFoundException 異常搁进;
? ? ? ?至此浪感,結(jié)束。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末饼问,一起剝皮案震驚了整個(gè)濱河市影兽,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌莱革,老刑警劉巖峻堰,帶你破解...
    沈念sama閱讀 216,324評(píng)論 6 498
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異盅视,居然都是意外死亡捐名,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,356評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門(mén)闹击,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)镶蹋,“玉大人,你說(shuō)我怎么就攤上這事赏半『毓椋” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 162,328評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵除破,是天一觀(guān)的道長(zhǎng)。 經(jīng)常有香客問(wèn)我琼腔,道長(zhǎng)瑰枫,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,147評(píng)論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮光坝,結(jié)果婚禮上尸诽,老公的妹妹穿的比我還像新娘。我一直安慰自己盯另,他們只是感情好性含,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,160評(píng)論 6 388
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著鸳惯,像睡著了一般商蕴。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上芝发,一...
    開(kāi)封第一講書(shū)人閱讀 51,115評(píng)論 1 296
  • 那天绪商,我揣著相機(jī)與錄音,去河邊找鬼辅鲸。 笑死格郁,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的独悴。 我是一名探鬼主播例书,決...
    沈念sama閱讀 40,025評(píng)論 3 417
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼刻炒!你這毒婦竟也來(lái)了决采?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 38,867評(píng)論 0 274
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤落蝙,失蹤者是張志新(化名)和其女友劉穎织狐,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體筏勒,經(jīng)...
    沈念sama閱讀 45,307評(píng)論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡移迫,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,528評(píng)論 2 332
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了管行。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片厨埋。...
    茶點(diǎn)故事閱讀 39,688評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖捐顷,靈堂內(nèi)的尸體忽然破棺而出荡陷,到底是詐尸還是另有隱情,我是刑警寧澤迅涮,帶...
    沈念sama閱讀 35,409評(píng)論 5 343
  • 正文 年R本政府宣布废赞,位于F島的核電站,受9級(jí)特大地震影響叮姑,放射性物質(zhì)發(fā)生泄漏唉地。R本人自食惡果不足惜据悔,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,001評(píng)論 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望耘沼。 院中可真熱鬧极颓,春花似錦、人聲如沸群嗤。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,657評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)狂秘。三九已至骇径,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間赃绊,已是汗流浹背既峡。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,811評(píng)論 1 268
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留碧查,地道東北人运敢。 一個(gè)月前我還...
    沈念sama閱讀 47,685評(píng)論 2 368
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像忠售,于是被迫代替她去往敵國(guó)和親传惠。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,573評(píng)論 2 353

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