Java類(java)一>字節(jié)碼文件(class)一>字節(jié)碼文件需要被加載到j(luò)vm內(nèi)存當(dāng)中(這個(gè)過程就是一個(gè)類加載的過程)
類加載器(ClassLoader傅瞻,說白了也是一個(gè)類旺拉,jvm啟動(dòng)的時(shí)候先把類加載器讀取到內(nèi)存當(dāng)中去,其他的類(比如各種jar中的字節(jié)碼文件,自己開發(fā)的代碼編譯之后的.class文件等等))
要說 Tomcat的類加載機(jī)制,首先需要來看看Jvm的類加載機(jī)制,因?yàn)?Tomcat類加載機(jī)制是在Jvm類加載機(jī)制基礎(chǔ)之上進(jìn)行了一些變動(dòng)痊焊。
JVM 的類加載機(jī)制
VM的類加載機(jī)制中有一個(gè)非常重要的角色叫做類加載器(ClassLoader),類加載器有自己的體系忿峻,Jvm內(nèi)置了幾種類加載器薄啥,包括∶引導(dǎo)類加載器、擴(kuò)展類加載器逛尚、系統(tǒng)類加載器垄惧,他們之間形成父子關(guān)系,通過Parent 屬性來定義這種關(guān)系绰寞,最終可以形成樹形結(jié)構(gòu)到逊。
另外∶用戶可以自定義類加載器Java編寫,用戶自定義的類加載器滤钱,可加載指定路徑的class文件)
當(dāng)JVM運(yùn)行過程中觉壶,用戶自定義了類加載器去加載某些類時(shí),會(huì)按照下面的步驟(父類委托機(jī)制)
1)用戶自己的類加載器件缸,把加載請(qǐng)求傳給父加載器铜靶,父加載器再傳給其父加載器,一直到加載器樹的頂層
2)最頂層的類加載器首先針對(duì)其特定的位置加載他炊,如果加載不到就轉(zhuǎn)交給子類
3)如果一直到底層的類加載都沒有加載到旷坦,那么就會(huì)拋出異常ClassNotFoundException
因此,按照這個(gè)過程可以想到佑稠,如果同樣在 classpath 指定的目錄中和自己工作目錄中存放相同的class,會(huì)優(yōu)先加載 classpath 目錄中的文件
雙親委派機(jī)制
什么是雙親委派機(jī)制
當(dāng)某個(gè)類加載器需要加載某個(gè).cass文件時(shí)旗芬,它首先把這個(gè)任務(wù)委托給他的上級(jí)類加載器舌胶,,遞歸這個(gè)操作疮丛,如果上級(jí)的類加載器沒有加載幔嫂,自己才會(huì)去加載這個(gè)類。
雙親委派機(jī)制的作用
- 防止重復(fù)加載同一個(gè).class誊薄。通過委托去向上面問一問履恩,加載過了,就不用再加載一遍呢蔫。保證數(shù)據(jù)安全切心。
- 保證核心.class不能被篡改飒筑。通過委托方式,不會(huì)去篡改核心.class绽昏,即使篡改也不會(huì)去加載协屡,即使加載也不會(huì)是同一個(gè).class對(duì)象了。不同的加載器加載同一個(gè).class也不是同一個(gè).class對(duì)象全谤。這樣保證了class執(zhí)行安全(如果子類加載器先加載肤晓,那么我們可以寫一些與java.lang包中基礎(chǔ)類同名的類,然后再定義一個(gè)子類加載器认然,這樣整個(gè)應(yīng)用使用的基礎(chǔ)類就都變成我們自己定義的類了补憾。
Object類-一>自定義類加載器(會(huì)出現(xiàn)問題的,那么真正的Object類就可能被篡改了)
Tomcat 的類加載機(jī)制
Tomcat的類加載機(jī)制相對(duì)于Jvm的類加載機(jī)制做了一些改變卷员。
沒有嚴(yán)格的遵從雙親委派機(jī)制盈匾,也可以說打破了雙親委派機(jī)制
比如∶有一個(gè)tomcat,webapps下部署了兩個(gè)應(yīng)用
app1lib/a-1.0.jar com.lagou.edu.Abc
app2/lib/a-2.0,jar com. lagou.edu.Abc
不同版本中Abc類的內(nèi)容是不同的子刮,代碼是不一樣的
- 引導(dǎo)類加載器 和 擴(kuò)展類加載器的作用不變
- 系統(tǒng)類加載器正常情況下加載的是CLASSPATH下的類威酒,但是Tomcat 的啟動(dòng)腳本并未使用該變量,而是加載tomcat啟動(dòng)的類挺峡,比如bootstrap.jar葵孤,通常在catalina.bat或者catalinash中指定。位CATALINA_HOME/bin下
- Common通用類加載器加載Tomcat使用以及應(yīng)用通用的一些類橱赠,位于CATALINAHOME/ib下尤仍,
比如servlet-api.jar - Catalina ClssLoader用于加載服務(wù)器內(nèi)部可見類陵珍,這些類應(yīng)用程序不能訪問
- Shared ClassLoader 用于加載應(yīng)用程序共享類税朴,這些類服務(wù)器不會(huì)依賴
- Webapp ClassLoader,每個(gè)應(yīng)用程序都會(huì)有一個(gè)獨(dú)一無二的Webapp lassLoader奸例,他用來加載
本應(yīng)用程序/WEB-INF/classes和/WEB-INF/ib 下的類饼拍。
tomcat 8.5默認(rèn)改變了嚴(yán)格的雙親委派機(jī)制
- 首先從Bootstrap Classloader加載指定的類
- 如果未加載到赡模,則從/WEB-INF/casses加載
- 如果未加載到,則從/WEB-INF/lib/*jar加載
- 如果未加載到师抄,則依次從System漓柑、Common、Shared加載(在這最后一步叨吮,遵從雙親委派機(jī)制)