虛擬機類加載機制(3)——線程上下文類加載器


之所以將線程上下文類加載器(Thread Context ClassLoader)單獨拿出來寫,確實是因為它涉及的東西比較多,既然帶有線程兩個字,一定也是非常重要的一個東西。

我們首先來回顧一下類加載器的雙親委派模型。

在上一章《虛擬機類加載機制(2)——類加載器》中我們解釋了何為類加載器的“雙親委派模型”,知道了雙親委派模型給我們帶了一個好處就是Java類隨着它的類一起具備了一種帶有優先級的層次關系。簡單的例子就是Object類在程序的各種類加載環境中都會由啟動類加載器來加載,換言之,它無論在什么環境中都是同一個Object類。但是有時候我們可能需要“打破”雙親委派模型。雙親委派模型讓我們加載基礎類的時候都是同一個基礎類,但我們有時候可能需要在基礎類中回調用戶代碼怎么辦呢?“基礎類中回調用戶代碼”可能不大好理解,我們列舉一個例子來說明:Java提供了很多服務提供者接口(SPI,Service Provider Interface),允許獨立廠商(第三方)為此提供實現。常見的SPI有:JNDI、JDBC、JAXP等。這些接口由Java的核心庫來提供,所以問題就在於,SPI的接口是Java核心庫的一部分,它們是由啟動類加載器來加載的。SPI實現的Java類一般是由應用程序類加載器(Application ClassLoader)來加載的。啟動類無法找到SPI的實現類,因為它只加載核心庫(SPI的實現類由第三方提供)。它也不能代理給應用程序類加載器,因為它又是應用程序類加載器的父類,雙親委派模型又會將它交給啟動類來加載。所以在這個時候我們就要“打破”這個“雙親委派模型”。

這個時候,線程上下文類加載器(Thread Context ClassLoader)很好地解決了這個問題。Thread類中有getContextClassLoader()和setContextClassLoader(ClassLoader cl)方法用來獲取和設置上下文類加載器,如果沒有setContextClassLoader(ClassLoader cl)方法通過設置類加載器,那么線程將繼承父線程的上下文類加載器,如果在應用程序的全局范圍內都沒有設置的話,那么這個上下文類加載器默認就是應用程序類加載器(Application ClassLoader),換句話說Java默認的線程上下文類加載器就是應用程序類加載器(AppClassLoader)。通過線程上下文來加載第三方庫jndi實現,而不依賴於雙親委派。大部分Java Application服務器(jboss, tomcat..)也是采用contextClassLoader來處理web服務(所以理解線程上下文類加載器,更能讓我們理解Tomcat等服務器的實現原理、工作方式)。

虛擬機的這幾個部分確實有難度,本人經驗知識有限也在努力學習中,尚不能給出專業且詳盡的分析,這里有一篇介紹上下文類加載的文章可以研讀此文。http://blog.csdn.net/zhoudaxia/article/details/35897057


免責聲明!

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



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