黄色网址大全免费-黄色网址你懂得-黄色网址你懂的-黄色网址有那些-免费超爽视频-免费大片黄国产在线观看

專注Java教育14年 全國咨詢/投訴熱線:400-8080-105
動力節點LOGO圖
始于2009,口口相傳的Java黃埔軍校
首頁 hot資訊 Tomcat類加載機制

Tomcat類加載機制

更新時間:2020-12-03 17:16:48 來源:動力節點 瀏覽1606次

說到Tomcat類加載機制,我們不得不提及JVM的類加載,然后Tomcat也是運行在JVM上的。所以,我們先拋磚引玉,一起來看看JVM類加載。

JVM類加載采用父類委托機制,當JVM運行過程中,用戶需要加載某些類時,用戶自己的類加載器,把加載請求傳給父加載器,父加載器再傳給其父加載器,一直到加載器樹的頂層。最頂層的類加載器首先針對其特定的位置加載,如果加載不到就轉交給子類。如果一直到底層的類加載都沒有加載到,那么就會拋出異常ClassNotFoundException。

回過頭來,我們再來看Tomcat類加載,Tomcat類加載機制是違反了雙親委托原則的,對于一些未加載的非基礎類(Object,String等),各個web應用自己的類加載器(WebAppClassLoader)會優先加載,加載不到時再交給commonClassLoader走雙親委托。

下面的簡圖是Tomcat9版本的官方文檔給出的Tomcat的類加載器的圖。

????Bootstrap
??????????|
???????System
??????????|
???????Common
???????/????\
??Webapp1 ??Webapp2 ..

Bootstrap :是Java的最高的加載器,用C語言實現,主要用來加載JVM啟動時所需要的核心類,例如$JAVA_HOME/jre/lib/ext路徑下的類。

System: 會加載CLASSPATH系統變量所定義路徑的所有的類。

Common:會加載Tomcat路徑下的lib文件下的所有類。

Webapp1、Webapp2……: 會加載webapp路徑下項目中的所有的類。一個項目對應一個WebappClassLoader,這樣就實現了應用之間類的隔離了。

這3個部分,在上面的Java雙親委派模型圖中都有體現。不過可以看到ExtClassLoader沒有畫出來,可以理解為是跟bootstrap合并了,都是去JAVA_HOME/jre/lib下面加載類。那么Tomcat為什么要自定義類加載器呢?

隔離不同應用:部署在同一個Tomcat中的不同應用A和B,例如A用了Spring2.5。B用了Spring3.5,那么這兩個應用如果使用的是同一個類加載器,那么Web應用就會因為jar包覆蓋而無法啟動。

靈活性:Web應用之間的類加載器相互獨立,那么就可以根據修改不同的文件重建不同的類加載器替換原來的。從而不影響其他應用。

性能:如果在一個Tomcat部署多個應用,多個應用中都有相同的類庫依賴。那么可以把這相同的類庫讓Common類加載器進行加載。

Tomcat自定義了WebAppClassLoader類加載器。打破了雙親委派的機制,即如果收到類加載的請求,會嘗試自己去加載,如果找不到再交給父加載器去加載,目的就是為了優先加載Web應用自己定義的類。我們知道ClassLoader默認的loadClass方法是以雙親委派的模型進行加載類的,那么Tomcat既然要打破這個規則,就要重寫loadClass方法,我們可以看WebAppClassLoader類中重寫的loadClass方法。

@Override
public Class loadClass(String name, boolean resolve) throws ClassNotFoundException {
????synchronized (getClassLoadingLock(name)) {
????????Class clazz = null;
// 1. 從本地緩存中查找是否加載過此類
????????clazz = findLoadedClass0(name);
????????if (clazz != null) {
????????????if (log.isDebugEnabled())
????????????????log.debug(" ?Returning class from cache");
????????????if (resolve)
????????????????resolveClass(clazz);
????????????return clazz;
????????}

// 2. 從AppClassLoader中查找是否加載過此類
????????clazz = findLoadedClass(name);
????????if (clazz != null) {
????????????if (log.isDebugEnabled())
????????????????log.debug(" ?Returning class from cache");
????????????if (resolve)
????????????????resolveClass(clazz);
????????????return clazz;
????????}

????????String resourceName = binaryNameToPath(name, false);
// 3. 嘗試用ExtClassLoader 類加載器加載類,防止Web應用覆蓋JRE的核心類
????????ClassLoader javaseLoader = getJavaseClassLoader();
????????boolean tryLoadingFromJavaseLoader;
????????try {
????????????URL url;
????????????if (securityManager != null) {
????????????????PrivilegedActiondp = new PrivilegedJavaseGetResource(resourceName);
????????????????url = AccessController.doPrivileged(dp);
????????????} else {
????????????????url = javaseLoader.getResource(resourceName);
????????????}
????????????tryLoadingFromJavaseLoader = (url != null);
????????} catch (Throwable t) {
????????????tryLoadingFromJavaseLoader = true;
????????}

????????boolean delegateLoad = delegate || filter(name, true);
?// 4. 判斷是否設置了delegate屬性,如果設置為true那么就按照雙親委派機制加載類
????????if (delegateLoad) {
????????????if (log.isDebugEnabled())
????????????????log.debug(" ?Delegating to parent classloader1 " + parent);
????????????try {
????????????????clazz = Class.forName(name, false, parent);
????????????????if (clazz != null) {
????????????????????if (log.isDebugEnabled())
????????????????????????log.debug(" ?Loading class from parent");
????????????????????if (resolve)
????????????????????????resolveClass(clazz);
????????????????????return clazz;
????????????????}
????????????} catch (ClassNotFoundException e) {
????????????????// Ignore
????????????}
????????}
? // 5. 默認是設置delegate是false的,那么就會先用WebAppClassLoader進行加載
????????if (log.isDebugEnabled())
????????????log.debug(" ?Searching local repositories");
????????try {
????????????clazz = findClass(name);
????????????if (clazz != null) {
????????????????if (log.isDebugEnabled())
????????????????????log.debug(" ?Loading class from local repository");
????????????????if (resolve)
????????????????????resolveClass(clazz);
????????????????return clazz;
????????????}
????????} catch (ClassNotFoundException e) {
????????????// Ignore
????????}

?// 6. 如果此時在WebAppClassLoader沒找到類,那么就委托給AppClassLoader去加載
????????if (!delegateLoad) {
????????????if (log.isDebugEnabled())
????????????????log.debug(" ?Delegating to parent classloader at end: " + parent);
????????????try {
????????????????clazz = Class.forName(name, false, parent);
????????????????if (clazz != null) {
????????????????????if (log.isDebugEnabled())
????????????????????????log.debug(" ?Loading class from parent");
????????????????????if (resolve)
????????????????????????resolveClass(clazz);
????????????????????return clazz;
????????????????}
????????????} catch (ClassNotFoundException e) {
????????????????// Ignore
????????????}
????????}
????}
????throw new ClassNotFoundException(name);
}

我們總結起來就是Web應用默認的類加載順序是(打破了雙親委派規則):

1.先從JVM的BootStrapClassLoader中加載。

2.加載Web應用下/WEB-INF/classes中的類。

3.加載Web應用下/WEB-INF/lib/*.jap中的jar包中的類。

4.加載上面定義的System路徑下面的類。

5.加載上面定義的Common路徑下面的類。

到此為止,Tomcat類加載機制逐漸明朗,Tomcat類加載機制的重點就是打破了雙親委派機制,WebAppClassLoader加載類的時候,繞開 AppClassLoader,直接先使用 ExtClassLoader 來加載類。這不僅保證了基礎類不會被同時加載,也

保證了在同一個 Tomcat 下不同 web 之間的 class 是相互隔離的。好了。Tomcat的類加載機制就講到這里,感興趣的小伙伴可以去觀看本站的Tomcat服務器教程,深入學習Tomcat里的各種技術。

提交申請后,顧問老師會電話與您溝通安排學習

免費課程推薦 >>
技術文檔推薦 >>
主站蜘蛛池模板: 国产亚洲第一伦理第一区 | 三级经典三级日本三级欧美 | 成人影院在线观看完整高清bd | 欧美色图在线观看 | 青青草国产精品人人爱99 | 中国国产成人精品久久 | 成人精品视频一区二区在线 | 一区二区视频在线观看免费的 | 黑人巨大videos极度另类 | 欧美国产永久免费看片 | 欧美一级高清片欧美国产欧美 | 成人久久18免费网 | 天天艹天天 | 欧美日韩三 | 黄色激情视频在线观看 | 手机在线观看黄色网址 | 亚洲综合成人在线 | 午夜小视频免费观看 | 在线观看黄视频 | 亚洲欧美日韩综合一区久久 | 精品亚洲综合久久中文字幕 | 天堂理论片 | 91在线公开视频 | 欧美精品不卡 | 又黄又爽又色的性视频 | 狠狠躁日日躁人人爽 | 日本黄色大片视频 | 嘿嘿连载黄色 | 午夜免费在线观看 | 一级韩国aa毛片免费观看 | 综合色图 | 成人国产在线看不卡 | freee性欧美 freevideos性欧美 | 黄色在线观看www | 国产成人一区二区三区影院免费 | 男女做羞羞的网站视频 | 羞羞视频在线免费看 | 久久精品亚洲综合 | 欧美激情一区二区三区在线 | 一级毛片免费视频观看 | 日韩精品1区 |