主流的Java Web服務器,如Tomcat、Jetty、WebLogic、WebSphere,都實現了本身定義的類加載器(通常都不止一個)。由於一個功能健全的Web服務器,要解決以下問題:java
因爲以上幾個要求,若是隻有一個CLASSPATH就很難實現了。因此各類Web服務器都會提供好幾個CLASSPATH路徑供用 戶存放第三方類庫,這些路徑通常都以lib或者classes命名。被放置在不一樣目錄的類庫,具有不一樣的訪問範圍和服務對象。一般而言,每個目錄都會有 一個對應的自定義類加載器去加載設置在裏面的Java類庫。那麼咱們就以Tomcat爲例來看一下。程序員
在Tomcat目錄結構中,有三組目錄能夠存放Java類庫,另外加上應用程序自身的目錄,一共四組:web
爲了支持這套目錄,並對目錄內的類庫進行加載和隔離,Tomcat自定義了幾個類加載器,這些類加載器按照經典的雙親委派模型來實現,以下圖所示:安全
其中WebAppClassLoader和JsperClassLoader會存在多個實例,每個WebApp對應一個WebApp類加載器,每個Jsp文件對應一個Jsp類加載器。服務器
上面的圖咱們也能看出它們之間的隔離性:架構
對於Tomcat的6.x版本,只有指定了conf/catalina.properties配置文件中的server.loader和 share.loader纔會真正創建CatalinaClassLoader和SharedClassLoader的實例,不然會以 CommonClassLoader代替。而默認的配置裏面是沒有設置這兩個loader的,因此Tomcat 6.x瓜熟蒂落的把/commmon、/server、/shared這三個目錄合併爲一個/lib目錄。這是Tomcat團隊爲了簡化大多數部署場景所 作的一項改進,若是默認設置不能知足需求,再經過修改配置完成3種類加載器的協同分工。app
傳說Java社區流傳這樣一句話:學習JEE規範,去看JBoss源碼;學習類加載器,去看OSGi源碼。可見,OSGi的類加載器機制確實值得學習。webapp
OSGi(Open Service Gateway Initiative)是OSGi聯盟制定的一個基於Java語言的動態模塊化規範,最初是Sun、IBM、愛立信等公司聯合發起,目的是使服務提供商經過住宅網關爲各類家用智能設備提供各類服務,後來這個規範在Java其餘技術領域都有不錯的發展,如今已經成爲Java世界中「事實上」的模塊化標準。OSGi在程序員中最著名的應用案例Eclipse。你對Eclipse進行設置後,不須要重啓就能夠完成某個功能的開啓或關閉,這就是OSGi的功勞。模塊化
看了以後,給個人感受就是這東西很是靈活。OSGi的基本單位是Bundle,每一個Bundle均可以有本身的類加載器和父加載器。而Bundle 和類也差很少,內部也是package和class組成。可是一個Bundle能夠聲明它依賴的Java Packeage(經過Import-Package描述),也能夠聲明它容許導出發佈的Java Package(經過Export-Package描述)。在OSGi中,Bundle之間的依賴關係從傳統的上層模塊依賴疊層模塊轉變爲平級模塊之間的依賴,並且類庫的可見性獲得了很是精確的控制,一個模塊裏只有被Export過的Package才能被外界訪問,其餘的Package和class會被隱藏。因此,OSGi才能支持熱插拔技術。學習
而OSGi擁有這麼誘人特性的緣由就是它的類加載器架構。舉一個簡單的例子:
那麼,三者之間的關係能夠用下圖表示:
從上圖能夠看出來,OSGi裏面的加載器再也不是雙親委派模型的樹形結構,而是進一步發展成了一種運行時才能肯定的網狀結構。更靈活的同時確定帶來了更復雜的使用方法,這點在實際應用中確實值得權衡。
通常來講,在OSGi中,加載一個類可能發生的查找行爲和委派關係會比上圖複雜的多,大致規則能夠總結爲: