本文由做者張遠道受權網易雲社區發佈。java
類加載器三傑bootstrap
jvm有三類classloader,分別是bootstrap classloader,extended classloader以及system classloader。windows
bootstrap classloader是系統在啓動jvm時默認加載的。當用戶在命令行輸入java Test時,系統會首先加載jvm。在windows系統下,jvm的路徑一般位於%JAVA_HOME%/jdk/jre/client/jvm.dll和%JAVA_HOME%/jdk/jre/server/jvm.dll.安全
bootstrap classloader加載後,會載入extended classloader,並將extended classloader的父類設爲bootstrap classloader。而後,bootstrap classloader接着載入system classloader,並將system classloader的父類設爲extended classloader。至此,bootstrap--extended--system三級繼承結構造成。服務器
bootstrap classloader在jvm啓動以後自動加載。bootstrap classloader由c實現,不屬於java類。jvm
extended classloader由java實現,一般爲sun.misc.Lancher$ExtClassLoader.post
system classloader由java實現,一般爲sun.misc.Lancher$AppClassLoader.動畫
其中,spa
bootstrap classloader負責加載sun.boot.class.path路徑下的.class文件以及jar包。.net
extended classloader負責加載java.ext.dirs路徑下的.class文件以及jar包。
system classloader負責加載java.class.path路徑下的.class文件以及jar包。
sun.boot.class.path一般對應環境變量CLASSPATH的路徑。
java.ext.dirs一般對應JAVA_HOME/jre/lib/ext目錄。
java.class.path對應用戶自身的類路徑。
類加載到何處
據可靠情報,jvm由方法區,堆,棧,pc寄存器和本地方法棧構成。類加載器的任務就是將class二進制文件加載到方法區,供虛擬機模製出在堆中存放的對象。
雙親委託機制
classloader加載類的過程爲:
檢查被加載類是否被加載。
若是沒有被加載則調用父classloader加載該類。
若是一、2不成功,則仍由自身進行類加載。
這種機制又叫雙親委派機制。
雙親委派機制的好處是,避免多個類加載器加載同一個類的不一樣拷貝到內存(jvm的方法區)中。由於若是類A由ClassLoaderA加載,同時,又被ClassLoaderB加載,這樣,內存中就會存在兩份不一樣的A的定義,因而造成A既是ClassLoaderA罩的,又是ClassLoaderB罩着,形成災難性後果。
用戶自定義類的加載順序一般爲:
首先調用AppClassLoader加載類,AppClassLoader調用ExtClassLoader,ExtClassLoader調用BootClassLoader,BootClassLoader在sun.boot.class.path尋找改類,沒找到,加載失敗;ExtClassLoader也未加載類,失敗,最後由AppClassLoader加載成功。從這個加載順序能夠看出來,三個類加載器的對類的可見性是不一樣的。
java中的類是由java的全名以及類的classloader來限定的。只有當兩者徹底同樣纔會認爲是同一個類。不然是不一樣的類。所以,能夠定義一個同名的類,包名也同樣,只要保證該類被不一樣的類加載器加載便可。
當前類加載器和線程上下文類加載器
當前類加載器
當前類加載器是指當前方法所在的類使用的類加載器。在程序中使用Class.forName或者Class.getResource抑或Class.class時就是使用的該類加載器。
線程上下文類加載器
線程上下文類加載器能夠不遵循雙親委派機制。線程的上下文類加載器有Thread.currentThread().setContextClassLoader()來爲當前線程設置線程上下文類加載器。若是沒有設置當前線程的上下文類加載器,則繼承父類的上下文類加載器。
爲何還須要線程上下文類加載器?
考慮一種狀況,當咱們的程序必須由jvm的核心代碼去加載第三方類的時候。好比jndi,jndi的核心是rt.jar包中實現的,由Bootstrap classloader負責加載,可是jndi必須加載第三方廠商的具體的jndi實現,這個時候調用Bootstrap加載只對其子類加載器可見的類,就會出現失敗。這個時候就可使用線程上下文類加載器。
免費領取驗證碼、內容安全、短信發送、直播點播體驗包及雲服務器等套餐
更多網易技術、產品、運營經驗分享請訪問網易雲社區。
相關文章:
【推薦】 MongoDB的正確使用姿式
【推薦】 掃臉動畫
【推薦】 AndroidTV開發(4)