關於java類加載器理解及暢談

每一種技術的出現無一不例外都是有現實的需求,就像java這門語言的誕生,正是因爲互聯網的發展,移動智能設備的誕生,網民數量的爆炸式增加,隨之而來的就是軟件業的興起。此時傳統彙編,C語言的複雜性就成了制約軟件發展的門檻,於是跨平臺,面向對象的java應運而生;同理web技術的誕生,90年代互聯網誕生之初,那時候的互聯網還只屬於少數人(科研機構),當時的web只是用來彼此交流一些靜態文檔,隨之誕生了HTTP協議,到今天的servlet動態網頁技術,以及web基礎設施tomcat,jetty等web服務器。

上面說的有點跑題,每次寫博客總能勾起我對一些技術變化的感慨,哈哈。因爲最近公司項目的需求,最近對java的類加載機制惡補了一下,下面做一些記錄,希望同樣對此感興趣的小夥伴有所受益,也方便自己以後查閱(希望csdn永存)。

首先我們列舉一下哪些需求可能會用到java classLoader技術(通常情況下,我們開發中很少直接去操作類加載器),以下是我目前能想到的一些用到classLoader 的場合,大家可以在評論裏面補充(工作時間越長越發現獨學不如衆學,歡迎大家拍磚)

場景一:熱部署

場景二:代碼加密

場景三:類層次劃分



在講解類加載器之前我們心裏一定要對類加載的機制有一個感性的認識:
(1)虛擬機把描述類的數據從(2)Class文件加載到內存,並對(3)數據進行校驗,轉化解析和初始化,最終形成可以被虛擬機直接使用的java類型,這就是虛擬機的類加載機制。
上面這句話的信息量很大呦(如果讀完上面這句話你沒有任何感覺,那你就需要學習一下虛擬機了,雖然平時編碼很少用到,它比較偏底層。但是如果你瞭解了上層的內功心法,各家功夫不過是招式套路而已。)。爲了更好的理解下面將要說的ClassLoader,有必要對上面的概念詳細理解一下:
(1):虛擬機:什麼叫虛擬機?限於篇幅,這裏簡單介紹。虛擬機是java生態中非常重要的一環,它是連接源碼跟機器碼的橋樑。沒有它,java所謂的誇平臺就是一句空話。打個比方:你會多國語言,當你用多種語言交流時如何讓不同國家的人都聽懂呢,那我們就需要多個翻譯或者一個會多國語言的翻譯。這裏面的翻譯就是虛擬機,不同的平臺都有自己的虛擬機(翻譯),所以我們java只跟虛擬機打交道,具體平臺的虛擬機跟平臺打交道,這也是我們平時寫程序一貫主張的松耦合,提高系統擴展性思想的體現。
(2):class文件:在java技術體系中對class文件的格式,內容有相關規定,這裏不在詳細說。你只需要知道,我們寫的java文件經編譯以後都轉化爲了該平臺對應虛擬機的字節碼(class文件),裏面記錄了我們的類信息(繼承,接口,訪問權限...).jvm規範中說加載class文件,只要是符合class格式標準的文件就可以被虛擬機所用,對class文件的來源並沒有做限制。此處可以做很多文章呦,好多很炫玩法依據都在於此呦!

類加載器的雙親委派模型:

雙親委派模型要求除了頂層的啓動類加載器外,其餘的類加載器都必須有自己的父類加載器,類加載器間的父子關係不會以繼承關係實現,而是以組合的方式來複用父類加載的代碼。


雙親委派模型的工作過程:

當一個類加載器收到類加載請求的時候,它會首先把這個請求委託給父類加載器去執行,因此所有的類加載請求最終都會傳送到頂層的啓動類加載器中(注意:啓動類加載器默認只會加載%JAVA_HME%/lib下的jar,而且是按照文件名字識別,自定義jar包不會加載,安全考慮!),只有當父類加載器也無法找到時纔會交給自己去加載。
  加載邏輯可以通過ClassLoader類中的loadClass找到,所以在自定義類加載器時需要繼承ClassLoader或者通過繼承URLClassLoader來間接繼承ClassLoader,但是建議不要重寫loadClass方法,破壞雙親委派的加載邏輯。

ClassLoader類中標準類加載邏輯:
protected synchronized Class<?> loadClass(String name,boolean resolve) throws ClassNotFoundException{
//是否已經加載過
Class c = findLoadedClass(name);
if(c == null){
try{
 if(parent != null){
 c= parent.loadClass(name,false);
}else{
c = findBootstrapClassOrNull(name);//委託啓動類加載器
}
}catch(ClassNotFoundException e){
//如果父類加載拋出異常,使用自己加載
c= findClass(name);
}
if(c == null){
c = findClass(name);
}
if(resolve){
resolveClass(name);
}
return c;


如果要自定義類加載器,用戶可以重寫findClass方法,不建議重寫loadClass方法(會破壞雙親委派模型)

 寫這部分發現涉及的東西很多,這篇就先寫到這裏,隨後關於類加載器這塊我會繼續寫。。。。。。。。


























發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章