溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

tomcat與類加載器的介紹

發(fā)布時間:2021-08-31 18:47:24 來源:億速云 閱讀:160 作者:chen 欄目:編程語言

本篇內(nèi)容介紹了“tomcat與類加載器的介紹”的有關知識,在實際案例的操作過程中,不少人都會遇到這樣的困境,接下來就讓小編帶領大家學習一下如何處理這些情況吧!希望大家仔細閱讀,能夠?qū)W有所成!

再次認識Tomcat

       Tomcat是我們從一開始接觸Java Web就認識的一個web服務器,它是由Java語言編寫的,主要的文件夾就是bin,conf,lib,logs,webapps這5個文件夾

tomcat與類加載器的介紹

Bin,是我們啟動,關閉tomcat的命令所在的文件夾

Conf,是我們tomcat相應配置所在的地方,在我們最早學習部署的時候,就有一種直接在conf中修改server.xml以及session過期時間之類的。

Lib,是tomcat所需依賴所在的文件夾,在之前5.x的版本中,并不直接是lib文件夾,而是分成了3個,common,server和shared三個文件夾,在下面我們來詳細說一下這3個被移除掉的東西對于現(xiàn)在的我們還有什么意義。

Logs,是tomcat運行中的日志記錄,當我們需要排查線上問題時,很多時候會需要通過查閱日志進行錯誤定位。

Webapps,這個我們應該是最熟悉的,因為我們部署項目都是扔到webapps里面然后啟動tomcat

Tomcat的類加載器

Tomcat也是使用Java編寫的一個web服務器,需要依賴Java環(huán)境,也就是說它的運行是需要基于JVM的,而用到JVM也就必然會使用類加載器來進行類加載。

Tomcat的類加載架構(gòu)如下圖所示

       tomcat與類加載器的介紹

       灰色背景的即我們之前提到過的JVM中原生的類加載器,分別負責的工作范圍大家可以通過上一篇文章回顧。而往下我們可以看到有Conmmon,Catalina,Shared,WebApp,JSP這幾種類加載器,在我們講解每個類加載器的作用前,先說一下tomcat 5.x的架構(gòu),便于我們理解。

       在tomcat 5.x的時候,并不是一個lib包,而是common,server和shared這三個文件夾,按照雙親委托機制,不同的類加載器負責不同的范圍,上圖的Common類加載器負責/common/*,Catalina類加載器負責/server/*,Shared類加載器負責/shared/*,而WebAppClassLoader就是我們webapps文件夾下每個項目對應的類加載器了。

       /common/*中的類可以被tomcat和所有的web應用程序共同使用。

       /server/*中的類可以被tomcat使用,而對web應用程序不可見。

       /shared/*中的類可以被web應用程序共同使用,而對tomcat不可見。

看到這里,上面問的第三個問題,如果有10個SSM架構(gòu)的項目,怎么節(jié)約內(nèi)存。答案就是可以通過把SSM的jar包放到/shared/文件夾中,整個tomcat運行只有這一份,所有web項目共用它來實現(xiàn)。

那么問題又來了,現(xiàn)在沒這些文件夾,只有一個lib包了,又該怎么辦。

Lib包現(xiàn)在相當于是common,我們把jar包放到common中雖然可以達到效果,但感覺會很混亂,因為這里面有tomcat運行所必須的依賴。所以我們需要把shared用上。

我們打開conf/Catalina.properties文件,可以看到這么一個默認的配置。

tomcat與類加載器的介紹

其中common.loader已經(jīng)有值了,而server.loader和shared.loader是沒有值的。對應上面我們說到的3個文件夾,想必各位同學應該是知道這每項代表的意思了。

那么我們可以直接在tomcat中建立shared文件夾,將需要共享的jar包放到文件夾中,然后配置shared.loader的值為文件夾的路徑,就可以用上了。

JSP

在我們開發(fā)過程中,如果使用的tomcat(或者其他一些主流的web服務器)和jsp的話,我們習慣于修改jsp之后直接切換到瀏覽器進行一次刷新,看改動是否生效,并不會去重啟項目,這就和我們前面說到的JasperLoader相關了。

WebAppClassLoader是每個web項目有一個,如我們舉例所說的10個項目,那么就有10個WebAppClassLoader,但JasperLoader就不止于此了。

我們有一個jsp文件,就有一個JasperLoader。

為什么需要這么多?

我們的JSP,大家都知道本質(zhì)上是個Servlet,也就是以字節(jié)碼文件的形式存在。在JSP文件被編譯后,我們會得到一個同名_jsp.class文件,然后被類加載器加載到JVM中使用。當服務器檢測到JSP被修改后,會替換掉該JSP當前的JasperLoader實例,然后當再次訪問到這個JSP頁面時,觸發(fā)它的編譯和類加載操作,此時就會再次創(chuàng)建一個JasperLoader用來加載JSP編譯得出的字節(jié)碼文件。

雙親委托機制的破壞

雙親委托機制并不是強制的要求,只是作為一種推薦的方式,在面對一些特殊的情況下,可能需要破壞這種機制。

這里所說的破壞并不見的是一種貶義的行為,換成突破二字可能會更好。

雙親委托機制存在一種缺陷,基礎類加載器只能加載自己指定范圍內(nèi)的類,對于用戶提供的類是沒法加載的,以至于如果基礎類需要用到用戶類,那就無法加載。比如JDBC,我們都知道這是Java提供了一個規(guī)范,由不同的廠商去實現(xiàn),這個規(guī)范通過接口體現(xiàn),作為基礎類,而廠商的實現(xiàn)是驅(qū)動包,放在我們項目的依賴包中。

我們可以使用DriverManager.getConnection(url,user,password)直接去獲取連接,而不手動去做賈璉欲執(zhí)事中的第一步,使用Class.forName()去加載驅(qū)動。這樣一來,DriverClassLoader會自動去尋找并加載驅(qū)動。如果嚴格按照雙親委托機制,DriverManager是java.sql包中的,屬于BootStrapClassLoader的范圍,它只能看到這個文件夾中的類,而我們的驅(qū)動包是不在這里面的,就無法找到類,也就沒法去加載了。那實際是怎么處理的呢?

tomcat與類加載器的介紹

我們可以看到這是getConnection重載的方法,我們直接傳入URL,user和password實際就是重載的這個方法。在這里我們可以看到獲取了調(diào)用者的類加載器,并且判斷了callerCL為null。同學們想一下,會有類沒有類加載器嗎?為null并不是說它沒有類加載器,而是因為它的類加載器是BootStrapClassLoader,這是由C++語言寫的,無法用Java對象表示。好,既然知道你是BootStrapClassLoader加載的了,那我就給你替換掉,替換成當前線程的線程上下文類加載器。這個類是在線程創(chuàng)建的時候,從父線程繼承或者默認直接取ApplicationClassLoader。換成ApplicationClassLoader了,那我們項目依賴的驅(qū)動包是不是也就很輕松的可以掃描并加載了?當然,如果你本身調(diào)用者所屬的類加載器就是Application Class Loader那都不用去線程中取了。

“tomcat與類加載器的介紹”的內(nèi)容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業(yè)相關的知識可以關注億速云網(wǎng)站,小編將為大家輸出更多高質(zhì)量的實用文章!

向AI問一下細節(jié)

免責聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI