classloader 結構,是否可以自己定義一個 java.lang.String 類,為什么? 雙親代理機制。


參考文獻:

  http://www.cnblogs.com/leesf456/p/5269545.html   

  http://www.cnblogs.com/doit8791/p/5820037.html

 

1. 雙親委派模型

  從虛擬機角度看,只存在兩種類加載器:1. 啟動類加載器。2. 其他類加載器。從開發人員角度看,包括如下類加載器:1. 啟動類加載器。2. 擴展類加載器。3. 應用程序類加載器。4. 自定義類加載器。

  ① 啟動類加載器,用於加載Java API,加載<JAVA_HOME>\lib目錄下的類庫。

  ② 擴展類加載類,由sun.misc.Launcher$ExtClassLoader實現,用於加載<JAVA_HOME>\lib\ext目錄下或者被java.ext.dirs系統變量指定路徑下的類庫。

  ③ 應用程序類加載器,也成為系統類加載器,由sun.misc.Launcher$AppClassLoader實現,用於加載用戶類路徑(ClassPath)上所指定的類庫。

  ④ 自定義類加載器,繼承系統類加載器,實現用戶自定義加載邏輯。

  各個類加載器之間是組合關系,並非繼承關系。

  當一個類加載器收到類加載的請求,它將這個加載請求委派給父類加載器進行加載,每一層加載器都是如此,最終,所有的請求都會傳送到啟動類加載器中。只有當父類加載器自己無法完成加載請求時,子類加載器才會嘗試自己加載。

  雙親委派模型可以確保安全性,可以保證所有的Java類庫都是由啟動類加載器加載。如用戶編寫的java.lang.Object,加載請求傳遞到啟動類加載器,啟動類加載的是系統中的Object對象,而用戶編寫的java.lang.Object不會被加載。如用戶編寫的java.lang.virus類,加載請求傳遞到啟動類加載器,啟動類加載器發現virus類並不是核心Java類,無法進行加載,將會由具體的子類加載器進行加載,而經過不同加載器進行加載的類是無法訪問彼此的。由不同加載器加載的類處於不同的運行時包。所有的訪問權限都是基於同一個運行時包而言的。 

  當一個類加載器收到類加載的請求,它將這個加載請求委派給父類加載器進行加載,每一層加載器都是如此,最終,所有的請求都會傳送到啟動類加載器中。只有當父類加載器自己無法完成加載請求時,子類加載器才會嘗試自己加載。

  雙親委派模型可以確保安全性,可以保證所有的Java類庫都是由啟動類加載器加載。如用戶編寫的java.lang.Object,加載請求傳遞到啟動類加載器,啟動類加載的是系統中的Object對象,而用戶編寫的java.lang.Object不會被加載。如用戶編寫的java.lang.virus類,加載請求傳遞到啟動類加載器,啟動類加載器發現virus類並不是核心Java類,無法進行加載,將會由具體的子類加載器進行加載,而經過不同加載器進行加載的類是無法訪問彼此的。由不同加載器加載的類處於不同的運行時包。所有的訪問權限都是基於同一個運行時包而言的。 

2.為什么要使用這種雙親委托模式呢?
因為這樣可以避免重復加載,當父親已經加載了該類的時候,就沒有必要子ClassLoader再加載一次。
考慮到安全因素,我們試想一下,如果不使用這種委托模式,那我們就可以隨時使用自定義的String來動態替代java核心api中定義類型,這樣會存在非常大的安全隱患,而雙親委托的方式,就可以避免這種情況,因為String已經在啟動時被加載,所以用戶自定義類是無法加載一個自定義的ClassLoader。

 

思考:假如我們自己寫了一個java.lang.String的類,我們是否可以替換調JDK本身的類?
答案是否定的。我們不能實現。為什么呢?我看很多網上解釋是說雙親委托機制解決這個問題,其實不是非常的准確。因為雙親委托機制是可以打破的,你完全可以自己寫一個classLoader來加載自己寫的java.lang.String類,但是你會發現也不會加載成功,具體就是因為針對java.*開頭的類,jvm的實現中已經保證了必須由bootstrp來加載。
 
 3.定義自已的ClassLoader
 
既然JVM已經提供了默認的類加載器,為什么還要定義自已的類加載器呢?
 
因為Java中提供的默認ClassLoader,只加載指定目錄下的jar和class,如果我們想加載其它位置的類或jar時,比如:我要加載網絡上的一個class文件,通過動態加載到內存之后,要調用這個類中的方法實現我的業務邏輯。在這樣的情況下,默認的ClassLoader就不能滿足我們的需求了,所以需要定義自己的ClassLoader。
 
定義自已的類加載器分為兩步:
 
1、繼承java.lang.ClassLoader
 
2、重寫父類的findClass方法
 
讀者可能在這里有疑問,父類有那么多方法,為什么偏偏只重寫findClass方法?
 
因為JDK已經在loadClass方法中幫我們實現了ClassLoader搜索類的算法,當在loadClass方法中搜索不到類時,loadClass方法就會調用findClass方法來搜索類,所以我們只需重寫該方法即可。如沒有特殊的要求,一般不建議重寫loadClass搜索類的算法。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM