哪些網(wǎng)站比較容易做鎮(zhèn)江推廣公司
? ? ? ? 回顧了一下雙親委派機(jī)制,在這記錄記錄,下一篇會(huì)基于打破雙親委派機(jī)制來(lái)更新
1.? 類(lèi)加載:
多個(gè)java文件經(jīng)過(guò)編譯打包后生成可運(yùn)行jar包,最后啟動(dòng)程序。首先需要通過(guò)類(lèi)加載器把主類(lèi)加載到JVM。主類(lèi)在運(yùn)行過(guò)程中如果使用到其他類(lèi),會(huì)逐步加載這些類(lèi)。(jar包里的類(lèi)不是一次性全部加載的,是使用到時(shí)才加載的)
?
類(lèi)加載到使用過(guò)程步驟:
加載 >> 驗(yàn)證 >> 準(zhǔn)備 >> 解析 >> 初始化 >> 使用 >> 卸載
?
?? 加載:在硬盤(pán)上查找并通過(guò)IO讀入字節(jié)碼文件,使用到類(lèi)時(shí)才會(huì)加載;
?? 驗(yàn)證:校驗(yàn)字節(jié)碼文件的正確性;
?? 準(zhǔn)備:給類(lèi)的靜態(tài)變量分配內(nèi)存,并賦予默認(rèn)值;
?? 解析:將符號(hào)引用替換為直接引用,會(huì)把一些靜態(tài)方法替換為指向數(shù)據(jù)所存內(nèi)存的指針或句柄等(直接引用),這是靜態(tài)鏈接過(guò)程;動(dòng)態(tài)鏈接是在程序運(yùn)行期間完成的將符號(hào)引用替換為直接引用。
?? 初始化:對(duì)類(lèi)的靜態(tài)變量初始化為指定的值,執(zhí)行靜態(tài)代碼塊。
?
?
?
2.類(lèi)加載器和雙親委派機(jī)制
? 類(lèi)加載器包括有:啟動(dòng)類(lèi)加載器,擴(kuò)展類(lèi)加載器,應(yīng)用類(lèi)加載器,自定義類(lèi)加載器
主要是:
? 啟動(dòng)類(lèi)加載器(bootstrap class loader):基于C++實(shí)現(xiàn),負(fù)責(zé)加載支撐JVM運(yùn)行的位于JRE的lib目錄下的核心類(lèi)庫(kù),比如rt.jar等;
? 擴(kuò)展類(lèi)加載器(ExtClassLoader):負(fù)責(zé)加載支撐JVM運(yùn)行的位于JRE的lib目錄下的ext擴(kuò)展目錄中的JAR類(lèi)包
? 應(yīng)用類(lèi)加載器(AppClassLoader):負(fù)責(zé)加載ClassPath路徑下的類(lèi)包,主要就是加載你自己寫(xiě)的那些類(lèi)
自定義加載器:負(fù)責(zé)加載用戶(hù)自定義路徑下的類(lèi)包
?
自定義一個(gè)類(lèi)加載器:
? ? ?自定義類(lèi)加載器需要繼承java.lang.ClassLoader?類(lèi),這個(gè)類(lèi)有兩個(gè)核心方法,一個(gè)是loadClass(String,boolean),實(shí)現(xiàn)了雙親委派機(jī)制,大概邏輯為:
?
1.?首先,檢查一下指定名稱(chēng)的類(lèi)是否已經(jīng)加載過(guò),如果加載過(guò)了,就不需要再加載,直接返回。
2.?如果此類(lèi)沒(méi)有加載過(guò),那么,再判斷一下是否有父加載器;如果有父加載器,則由父加載器加載(即調(diào)用parent.loadClass(name,?false);).或者是調(diào)用bootstrap類(lèi)加載器來(lái)加載。
3.?如果父加載器及bootstrap類(lèi)加載器都沒(méi)有找到指定的類(lèi),那么調(diào)用當(dāng)前類(lèi)加載器的findClass方法來(lái)完成類(lèi)加載。
?
還有一個(gè)方法是findClass,默認(rèn)實(shí)現(xiàn)是拋出異常,所以自定義類(lèi)加載器主要是重寫(xiě)findClass()方法。
?
?
雙親委派機(jī)制:
?
JVM類(lèi)加載器有親子層級(jí)結(jié)構(gòu):
?
雙親委派機(jī)制說(shuō)簡(jiǎn)單點(diǎn)就是,先找父親加載,不行再由兒子自己加載。
我在自己實(shí)驗(yàn)過(guò)程中發(fā)現(xiàn),當(dāng)我刪除classpath下編譯的類(lèi)時(shí),通過(guò)自定義類(lèi)加載器加載我指定路徑的類(lèi)文件,打印出為我自己的類(lèi)加載器加載;當(dāng)我將classpath下的該類(lèi)復(fù)原時(shí),再次打印類(lèi)加載器時(shí),返回的則是應(yīng)用類(lèi)加載器了,說(shuō)明雙親委派機(jī)制的加載層級(jí)關(guān)系。
?
為什么設(shè)計(jì)雙親委派機(jī)制呢?
- 沙箱安全機(jī)制:自己編寫(xiě)的String類(lèi)不會(huì)被加載,可以防止核心API庫(kù)被隨意篡改;
- 避免類(lèi)的重復(fù)加載:當(dāng)父類(lèi)已經(jīng)加載了該類(lèi)時(shí),就沒(méi)有必要子類(lèi)加載器再次加載一次,保證被加載類(lèi)的唯一性。
?
打破雙親委派機(jī)制:
?
? 例如tomcat:在webapp下存在多個(gè)項(xiàng)目時(shí),所加載的是單獨(dú)隔離的,每個(gè)webappClassLoader加載自己的目錄下的class文件,不會(huì)傳遞給父類(lèi)加載器,打破了雙
親委派機(jī)制。
?
tomcat的幾個(gè)主要類(lèi)加載器:
commonLoader:Tomcat最基本的類(lèi)加載器,加載路徑中的class可以被Tomcat容器本身以及各個(gè)Webapp訪(fǎng)問(wèn);
catalinaLoader:Tomcat容器私有的類(lèi)加載器,加載路徑中的class對(duì)于Webapp不可見(jiàn);
sharedLoader:各個(gè)Webapp共享的類(lèi)加載器,加載路徑中的class對(duì)于所有Webapp可見(jiàn),但是對(duì)于Tomcat容器不可見(jiàn);
WebappClassLoader:各個(gè)Webapp私有的類(lèi)加載器,加載路徑中的class只對(duì)當(dāng)前Webapp可見(jiàn);
?
實(shí)現(xiàn)打破雙親委派機(jī)制,在原來(lái)重寫(xiě)findClass基礎(chǔ)上,對(duì)于加載類(lèi)loadClass方法進(jìn)行重寫(xiě),取出雙親委派部分。
?