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è)指定的類找到對應(yīng)的字節(jié)碼,然后根據(jù)這些字節(jié)碼定義一個(gè)java類。另外,它還可以加載資源,包括圖像文件和配置文件。
類加載器可以使java類動態(tài)地加載到j(luò)vm中并運(yùn)行,即可在程序運(yùn)行時(shí)再加載類,提供了很靈活的動態(tài)加載方式。
- 啟動類加載器(Bootstrap ClassLoader):加載對象是java核心庫,把一些核心的java類加載進(jìn)jvm中,這個(gè)加載器采用原生代碼(c/c++)實(shí)現(xiàn),并不繼承java.lang.classLoader,它是所有其他類加載器的最終父類加載器,負(fù)責(zé)加載<java_home>/jre/lib目錄下jvm指定的類庫。它屬于jvm整體的一部分,jvm一旦啟動就將這些指定的類加載到內(nèi)存中國,避免以后過多的I/O操作,提高系統(tǒng)的運(yùn)行效率。啟動類加載器無法被程序直接使用。
- 擴(kuò)展類加載器(Extension ClassLoader):加載對象是java的擴(kuò)展庫,即加載<java_home>/jar/lib/ext目錄里的類。這個(gè)類是由啟動類加載器加載,但因?yàn)閱宇惣虞d器并非用java實(shí)現(xiàn),已經(jīng)脫離了java體系,所以如果嘗試調(diào)用擴(kuò)展類加載器的getParent()方法獲取父類的加載器會得到null。然而,它的父類加載器是啟動類加載器。
- 應(yīng)用類加載器(application ClassLoader):也叫系統(tǒng)類加載器(system classloader),它負(fù)責(zé)加載用戶類路徑自定的類庫,如果程序沒有自己定義類加載器,就默認(rèn)使用應(yīng)用類加載器。它是由啟動類加載器加載,但他的父加載類被設(shè)置成了擴(kuò)展類加載器。如果使用這個(gè)加載器,通過classloader.getSystemClassLoader()獲取。
雙親委派
雙親委派時(shí),會將先委托給父類加載器加載,除非父類加載器沒有,才自己加載。
這種模型要求,除了頂層的啟動類加載器外,其他的類加載器都要有⾃⼰的⽗類加載器。 假如有⼀個(gè)類要加載進(jìn)來,⼀個(gè)類加載器并不會⻢上嘗試⾃⼰將其加載,⽽是委派給⽗類加載器,⽗類加載器收到后⼜嘗 試委派給其⽗類加載器,以此類推,直到委派給啟動類加載器,這樣⼀層⼀層往上委派。 只有當(dāng)⽗類加載器反饋⾃⼰沒法完成這個(gè)加載時(shí),⼦加載器才會嘗試⾃⼰加載。 通過這個(gè)機(jī)制,保證了 Java 應(yīng)⽤所使⽤的都是同⼀個(gè)版本的 Java 核⼼庫的類,同時(shí)這個(gè)機(jī)制也保證了安全性。 設(shè)想如果應(yīng)⽤程序類加載器想要加載⼀個(gè)有破壞性的 java.lang.System 類,雙親委派模型會⼀層層向上委派,最終委派給啟動類加載器,⽽啟動類加載器檢查到緩存中已經(jīng)有了這個(gè)類,并不會再加載這個(gè)有破壞性的 System 類。
另外,類加載器還擁有全盤負(fù)責(zé)機(jī)制,即當(dāng)⼀個(gè)類加載器加載⼀個(gè)類時(shí),這個(gè)類所依賴的、 引⽤的其他所有類都由這個(gè)類加載器加載,除⾮在程序中顯式地指定另外⼀個(gè)類加載器加載。
在 Java 中,我們⽤完全匹配類名來標(biāo)識⼀個(gè)類,即⽤包名和類名。 ⽽在 JVM 中,⼀個(gè)類由完全匹配類名和⼀個(gè)類加載器的實(shí)例 ID 作為唯⼀標(biāo)識。 也就是說,同⼀個(gè)虛擬機(jī)可以有兩個(gè)包名、 類名都相同的類,只要它們由兩個(gè)不同的類加載器加載。 當(dāng)我們在 Java 中說兩個(gè)類是否相等時(shí),必須在針對同⼀個(gè)類加載器加載的前提下才有意義,否則,就算是同樣的字節(jié)碼,由不同的類加載器加載,這兩個(gè)類也不是相等的。 這種特征為我們提供了隔離機(jī)制,在 Tomcat 服務(wù)器中它是⼗分有⽤的。
URLClassLoader
我們在使⽤⾃定義類加載去加載類時(shí),我們需要指明該去哪些資源中進(jìn)⾏加載,所以JDK提供了URLClassLoader來⽅便我們使⽤,我們在創(chuàng)建URLClassLoader時(shí)需要傳⼊⼀些URLs,然后在使⽤這個(gè)URLClassLoader加載類時(shí)就會從這些資源中去加載。
Tomcat中⾃定義的類加載器
Tomcat 擁有不同的⾃定義類加載器,以實(shí)現(xiàn)對各種資源庫的控制。 ⼀般來說,Tomcat 主要⽤類加載器解決以下 4 個(gè)問題。
- 同⼀個(gè)Tomcat中,各個(gè)Web應(yīng)⽤之間各⾃使⽤的Java類庫要互相隔離。
- 同⼀個(gè)Tomcat中,各個(gè)Web應(yīng)⽤之間可以提供共享的Java類庫。
為了使Tomcat不受Web應(yīng)⽤的影響,應(yīng)該使服務(wù)器的類庫與應(yīng)⽤程序的類庫互相獨(dú)⽴。
-Tomcat⽀持熱部署。
在 Tomcat中,最重要的⼀個(gè)類加載器是 Common 類加載器,它的⽗類加載器是應(yīng)⽤程序類加載器,負(fù)責(zé)加載 $ CATALINA_ BASE/lib、$CATALINA_HOME/lib 兩個(gè)⽬錄下所有的.class ⽂件與.jar ⽂件。
-Tomcat中⼀般會有多個(gè)WebApp類加載器-WebAppClassLoader ,每個(gè)類加載器負(fù)責(zé)加載⼀個(gè) Web 程序。 它的⽗類加載器是Common類加載器。
由于每個(gè) Web 應(yīng)⽤都有⾃⼰的 WebApp 類加載器,很好地使多個(gè) Web 應(yīng)⽤程序之間互相隔離且能通過創(chuàng)建新的 WebApp類加載器達(dá)到熱部署。 這種類加載器結(jié)構(gòu)能有效使 Tomcat 不受 Web 應(yīng)⽤程序影響,
⽽ Common 類加載器的存在使多個(gè) Web 應(yīng)⽤程序能夠互相共享類庫
Tomcat中類加載器架構(gòu)

源碼位置如下,在bootstrap類的初始化過程中,初始了三個(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)⾏過程中擁有的權(quán)限,Tomcat管理者可以修改該權(quán)限, 但是Tomcat中有⼀些類是必須能夠被訪問到的,所有Tomcat中在啟動過程中會提前去加載這些類,如果 發(fā)現(xiàn)沒有對應(yīng)的權(quán)限,那么將會啟動失敗。
總結(jié)
本篇文章就到這里了,希望能夠給你帶來幫助,也希望您能夠多多關(guān)注腳本之家的更多內(nèi)容!
相關(guān)文章
Spring Boot基礎(chǔ)入門之基于注解的Mybatis
這篇文章主要給大家介紹了關(guān)于Spring Boot基礎(chǔ)入門之基于注解的Mybatis的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2018-07-07
scala+redis實(shí)現(xiàn)分布式鎖的示例代碼
這篇文章主要介紹了scala+redis實(shí)現(xiàn)分布式鎖的示例代碼,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-06-06
Java注解詳解及實(shí)現(xiàn)自定義注解的方法
這篇文章主要介紹了Java注解詳解及實(shí)現(xiàn)自定義注解的方法,本文給大家介紹了jdk中預(yù)定義的一些注解及自定義注解的相關(guān)知識,需要的朋友可以參考下2022-06-06
SpringMVC @ResponseBody 415錯(cuò)誤處理方式
這篇文章主要介紹了SpringMVC @ResponseBody 415錯(cuò)誤處理方式,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-11-11
SpringBoot使用Maven實(shí)現(xiàn)多環(huán)境配置管理
軟件開發(fā)中經(jīng)常有開發(fā)環(huán)境、測試環(huán)境、生產(chǎn)環(huán)境,而且一般這些環(huán)境配置會各不相同,本文主要介紹了SpringBoot使用Maven實(shí)現(xiàn)多環(huán)境配置管理,感興趣的可以了解一下2024-01-01
java 中模擬TCP傳輸?shù)目蛻舳撕头?wù)端實(shí)例詳解
這篇文章主要介紹了java 中模擬TCP傳輸?shù)目蛻舳撕头?wù)端實(shí)例詳解的相關(guān)資料,需要的朋友可以參考下2017-03-03
Maven install 報(bào)錯(cuò)"程序包不存在"問題的解決方法
這篇文章主要介紹了Maven install 報(bào)錯(cuò)"程序包不存在"問題的解決方法,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-07-07

