Java tomcat中的類加載器和安全機(jī)制你了解嗎
類加載器
java中的類并不是一次加載完成的,而是按需加載。類加載器是用于加載java類到j(luò)ava虛擬機(jī)中的組件,它負(fù)責(zé)讀取java字節(jié)碼,并轉(zhuǎn)換成 java.lang.Class 的一個(gè)實(shí)例,使字節(jié)碼.class文件可以運(yùn)行。一般類加載器負(fù)責(zé)根據(jù)一個(gè)指定的類找到對(duì)應(yīng)的字節(jié)碼,然后根據(jù)這些字節(jié)碼定義一個(gè)java類。另外,它還可以加載資源,包括圖像文件和配置文件。
類加載器可以使java類動(dòng)態(tài)地加載到j(luò)vm中并運(yùn)行,即可在程序運(yùn)行時(shí)再加載類,提供了很靈活的動(dòng)態(tài)加載方式。
- 啟動(dòng)類加載器(Bootstrap ClassLoader):加載對(duì)象是java核心庫(kù),把一些核心的java類加載進(jìn)jvm中,這個(gè)加載器采用原生代碼(c/c++)實(shí)現(xiàn),并不繼承java.lang.classLoader,它是所有其他類加載器的最終父類加載器,負(fù)責(zé)加載<java_home>/jre/lib目錄下jvm指定的類庫(kù)。它屬于jvm整體的一部分,jvm一旦啟動(dòng)就將這些指定的類加載到內(nèi)存中國(guó),避免以后過(guò)多的I/O操作,提高系統(tǒng)的運(yùn)行效率。啟動(dòng)類加載器無(wú)法被程序直接使用。
- 擴(kuò)展類加載器(Extension ClassLoader):加載對(duì)象是java的擴(kuò)展庫(kù),即加載<java_home>/jar/lib/ext目錄里的類。這個(gè)類是由啟動(dòng)類加載器加載,但因?yàn)閱?dòng)類加載器并非用java實(shí)現(xiàn),已經(jīng)脫離了java體系,所以如果嘗試調(diào)用擴(kuò)展類加載器的getParent()方法獲取父類的加載器會(huì)得到null。然而,它的父類加載器是啟動(dòng)類加載器。
- 應(yīng)用類加載器(application ClassLoader):也叫系統(tǒng)類加載器(system classloader),它負(fù)責(zé)加載用戶類路徑自定的類庫(kù),如果程序沒有自己定義類加載器,就默認(rèn)使用應(yīng)用類加載器。它是由啟動(dòng)類加載器加載,但他的父加載類被設(shè)置成了擴(kuò)展類加載器。如果使用這個(gè)加載器,通過(guò)classloader.getSystemClassLoader()獲取。
雙親委派
雙親委派時(shí),會(huì)將先委托給父類加載器加載,除非父類加載器沒有,才自己加載。
這種模型要求,除了頂層的啟動(dòng)類加載器外,其他的類加載器都要有⾃⼰的⽗類加載器。 假如有⼀個(gè)類要加載進(jìn)來(lái),⼀個(gè)類加載器并不會(huì)⻢上嘗試⾃⼰將其加載,⽽是委派給⽗類加載器,⽗類加載器收到后⼜嘗 試委派給其⽗類加載器,以此類推,直到委派給啟動(dòng)類加載器,這樣⼀層⼀層往上委派。 只有當(dāng)⽗類加載器反饋⾃⼰沒法完成這個(gè)加載時(shí),⼦加載器才會(huì)嘗試⾃⼰加載。 通過(guò)這個(gè)機(jī)制,保證了 Java 應(yīng)⽤所使⽤的都是同⼀個(gè)版本的 Java 核⼼庫(kù)的類,同時(shí)這個(gè)機(jī)制也保證了安全性。 設(shè)想如果應(yīng)⽤程序類加載器想要加載⼀個(gè)有破壞性的 java.lang.System 類,雙親委派模型會(huì)⼀層層向上委派,最終委派給啟動(dòng)類加載器,⽽啟動(dòng)類加載器檢查到緩存中已經(jīng)有了這個(gè)類,并不會(huì)再加載這個(gè)有破壞性的 System 類。
另外,類加載器還擁有全盤負(fù)責(zé)機(jī)制,即當(dāng)⼀個(gè)類加載器加載⼀個(gè)類時(shí),這個(gè)類所依賴的、 引⽤的其他所有類都由這個(gè)類加載器加載,除⾮在程序中顯式地指定另外⼀個(gè)類加載器加載。
在 Java 中,我們⽤完全匹配類名來(lái)標(biāo)識(shí)⼀個(gè)類,即⽤包名和類名。 ⽽在 JVM 中,⼀個(gè)類由完全匹配類名和⼀個(gè)類加載器的實(shí)例 ID 作為唯⼀標(biāo)識(shí)。 也就是說(shuō),同⼀個(gè)虛擬機(jī)可以有兩個(gè)包名、 類名都相同的類,只要它們由兩個(gè)不同的類加載器加載。 當(dāng)我們?cè)?Java 中說(shuō)兩個(gè)類是否相等時(shí),必須在針對(duì)同⼀個(gè)類加載器加載的前提下才有意義,否則,就算是同樣的字節(jié)碼,由不同的類加載器加載,這兩個(gè)類也不是相等的。 這種特征為我們提供了隔離機(jī)制,在 Tomcat 服務(wù)器中它是⼗分有⽤的。
URLClassLoader
我們?cè)谑?#12132;⾃定義類加載去加載類時(shí),我們需要指明該去哪些資源中進(jìn)⾏加載,所以JDK提供了URLClassLoader來(lái)⽅便我們使⽤,我們?cè)趧?chuàng)建URLClassLoader時(shí)需要傳⼊⼀些URLs,然后在使⽤這個(gè)URLClassLoader加載類時(shí)就會(huì)從這些資源中去加載。
Tomcat中⾃定義的類加載器
Tomcat 擁有不同的⾃定義類加載器,以實(shí)現(xiàn)對(duì)各種資源庫(kù)的控制。 ⼀般來(lái)說(shuō),Tomcat 主要⽤類加載器解決以下 4 個(gè)問(wèn)題。
- 同⼀個(gè)Tomcat中,各個(gè)Web應(yīng)⽤之間各⾃使⽤的Java類庫(kù)要互相隔離。
- 同⼀個(gè)Tomcat中,各個(gè)Web應(yīng)⽤之間可以提供共享的Java類庫(kù)。
為了使Tomcat不受Web應(yīng)⽤的影響,應(yīng)該使服務(wù)器的類庫(kù)與應(yīng)⽤程序的類庫(kù)互相獨(dú)⽴。
-Tomcat⽀持熱部署。
在 Tomcat中,最重要的⼀個(gè)類加載器是 Common 類加載器,它的⽗類加載器是應(yīng)⽤程序類加載器,負(fù)責(zé)加載 $ CATALINA_ BASE/lib、$CATALINA_HOME/lib 兩個(gè)⽬錄下所有的.class ⽂件與.jar ⽂件。
-Tomcat中⼀般會(huì)有多個(gè)WebApp類加載器-WebAppClassLoader ,每個(gè)類加載器負(fù)責(zé)加載⼀個(gè) Web 程序。 它的⽗類加載器是Common類加載器。
由于每個(gè) Web 應(yīng)⽤都有⾃⼰的 WebApp 類加載器,很好地使多個(gè) Web 應(yīng)⽤程序之間互相隔離且能通過(guò)創(chuàng)建新的 WebApp類加載器達(dá)到熱部署。 這種類加載器結(jié)構(gòu)能有效使 Tomcat 不受 Web 應(yīng)⽤程序影響,
⽽ Common 類加載器的存在使多個(gè) Web 應(yīng)⽤程序能夠互相共享類庫(kù)
Tomcat中類加載器架構(gòu)
源碼位置如下,在bootstrap類的初始化過(guò)程中,初始了三個(gè)類加載:commonLoader,catalinaLoader,sharedLoader
private void initClassLoaders() { try { commonLoader = createClassLoader("common", null); if (commonLoader == null) { // no config file, default to this loader - we might be in a 'single' env. commonLoader = this.getClass().getClassLoader(); } catalinaLoader = createClassLoader("server", commonLoader); sharedLoader = createClassLoader("shared", commonLoader); } catch (Throwable t) { handleThrowable(t); log.error("Class loader creation threw exception", t); System.exit(1); } }
安全機(jī)制
Tomcat中設(shè)置了了⼀些安全策略,默認(rèn)的策略⽂件為conf/catalina.policy
Tomcat中設(shè)置了安全策略,規(guī)定了Tomcat在運(yùn)⾏過(guò)程中擁有的權(quán)限,Tomcat管理者可以修改該權(quán)限, 但是Tomcat中有⼀些類是必須能夠被訪問(wèn)到的,所有Tomcat中在啟動(dòng)過(guò)程中會(huì)提前去加載這些類,如果 發(fā)現(xiàn)沒有對(duì)應(yīng)的權(quán)限,那么將會(huì)啟動(dòng)失敗。
總結(jié)
本篇文章就到這里了,希望能夠給你帶來(lái)幫助,也希望您能夠多多關(guān)注腳本之家的更多內(nèi)容!
相關(guān)文章
Spring Boot整合mybatis(一)實(shí)例代碼
sprig-boot是一個(gè)微服務(wù)架構(gòu),加快了spring工程快速開發(fā),以及簡(jiǎn)便了配置。接下來(lái)開始spring-boot與mybatis的整合2017-07-07springboot-mybatis/JPA流式查詢的多種實(shí)現(xiàn)方式
這篇文章主要介紹了springboot-mybatis/JPA流式查詢,本文給大家分享三種方式,每種方式結(jié)合示例代碼給大家講解的非常詳細(xì),需要的朋友可以參考下2022-12-12Springboot編寫CRUD時(shí)訪問(wèn)對(duì)應(yīng)數(shù)據(jù)函數(shù)返回null的問(wèn)題及解決方法
我在學(xué)習(xí)springboot,其中在編寫CRUD時(shí)發(fā)現(xiàn)訪問(wèn)數(shù)據(jù)的函數(shù)執(zhí)行下去返回值是null但是其它部分正常,這篇文章主要介紹了Springboot在編寫CRUD時(shí),訪問(wèn)對(duì)應(yīng)數(shù)據(jù)函數(shù)返回null,需要的朋友可以參考下2024-02-02MybatisPlus調(diào)用原生SQL的實(shí)現(xiàn)方法
本文主要介紹了MybatisPlus調(diào)用原生SQL的實(shí)現(xiàn)方法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2023-02-02java雙端隊(duì)列之ArrayDequeue原理講解
這篇文章主要為大家介紹了java雙端隊(duì)列之ArrayDequeue原理講解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-06-06微信公眾號(hào)支付(二)實(shí)現(xiàn)統(tǒng)一下單接口
本篇文章主要給大家介紹調(diào)用微信公眾支付的統(tǒng)一下單API,通過(guò)參數(shù)封裝為xml格式并發(fā)送到微信給的接口地址就可以獲得返回內(nèi)容,需要的朋友可以參考下本文2015-09-09Java中Bean轉(zhuǎn)Map問(wèn)題歸納總結(jié)
Java Bean轉(zhuǎn)Map的坑很多,最常見的就是類型丟失和屬性名解析錯(cuò)誤的問(wèn)題,下面這篇文章主要給大家介紹了關(guān)于Java中Bean轉(zhuǎn)Map問(wèn)題歸納總結(jié)的相關(guān)資料,文中通過(guò)實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下2023-06-06