ContextClassLoader java
爲線程上下文加載器,正常的雙親委派模型中,下層的類加載器能夠使用上層父加載器加載的對象,可是上層父類的加載器不能夠使用子類加載的對象。而有些時候程序的確須要上層調用下層,這時候就須要線程上下文加載器來處理。 編程
這一般發生在JVM核心代碼必須動態加載由應用程序動態提供的資源時。拿JNDI爲例,它的核心是由JRE核心類(rt.jar)實現的。但這些核心JNDI類必須能加載由第三方廠商提供的JNDI實現。這種狀況下調用父類加載器(原初類加載器)來加載只有其子類加載器可見的類,這種代理機制就會失效。解決辦法就是讓核心JNDI類使用線程上下文類加載器,從而有效的打通類加載器層次結構,逆着代理機制的方向使用類加載器。 服務器
順便提一下,XML解析API(JAXP)也是使用此種機制。當JAXP仍是J2SE擴展時,XML解析器使用當前類加載器方法來加載解析器實現。但當JAXP成爲J2SE核心代碼後,類加載機制就換成了使用線程上下文加載器,這和JNDI的緣由類似。 框架
更嚴重的問題, 某些應用服務器把環境上下文及當前類加載器設置到不一樣的類加載器實例上, 而這些類加載器有相同的類路徑但卻沒有委派機制中的父子關係. 想一想這爲何十分可怕. 要知道類加載器定義並加載的類實例會帶有一個JVM內部的ID號. 若是當前類加載器加載一個類X的實例, 這個實例調用JNDI查找類Y的實例, 這時的上下文的類加載器也能夠定義了加載類Y實例. 這個類Y的定義就與當前類加載器看到的類Y的定義不一樣. 若是進行強制類型轉換, 則產生異常。 spa
這種混亂的情況還將在Java中存在很長時間。在J2SE中還包括如下的功能使用不一樣的類加載器: 線程
l JNDI使用線程上下文類加載器 代理
l Class.getResource()和Class.forName()使用當前類加載器 對象
l JAXP使用上下文類加載器 blog
l java.util.ResourceBundle使用調用者的當前類加載器 資源
l URL協議處理器使用java.protocol.handler.pkgs系統屬性並只使用系統類加載器。
l Java序列化API缺省使用調用者當前的類加載器