Thread.currentThread().getContextClassLoader() 和 Class.getClassLoader()區別


Thread.currentThread().getContextClassLoader() 和 Class.getClassLoader()區別

查了一些資料也不是太明白兩個的區別,但是前者是最安全的用法

 

忘記以前有沒有問過這個問題,總之我現在有看到幾個地方有這個:
Thread.currentThread().getContextClassLoader()
我總是想不出在什么情況下會用這種方式獲得一個ClassLoader,因為好像默認情況下,它返回的是和加載應用的ClassLoader是同一個,比如說在一個類Test中寫
ClassLoader cl = Thread.currentThread().getContextClassLoader();
為何不直接用Test.class.getClassLoader()

獲得當前上下文的類加載器是啥意思?有啥好處?
 
 
 
Java code
 
?
1
2
3
4
5
6
7
8
9
10
11
public  class  Test {
 
     public  static  void  main(String[] args) {
         
         // 此時三個ClassLoader是同一個對象
         System.out.println(Thread.currentThread().getContextClassLoader());  // 當前線程的類加載器
         System.out.println(Test. class .getClassLoader());  // 當前類的類加載器
         System.out.println(ClassLoader.getSystemClassLoader());  // 系統初始的類加載器
         
     }
}


如果樓主了解過openfire應該對ClassLoader有比較深的理解。
打個簡單的比方,你一個WEB程序,發布到Tomcat里面運行。
首先是執行Tomcat org.apache.catalina.startup.Bootstrap類,這時候的類加載器是ClassLoader.getSystemClassLoader()。
而我們后面的WEB程序,里面的jar、resources都是由Tomcat內部來加載的,所以你在代碼中動態加載jar、資源文件的時候,首先應該是使用Thread.currentThread().getContextClassLoader()。如果你使用Test.class.getClassLoader(),可能會導致和當前線程所運行的類加載器不一致(因為Java天生的多線程)。
Test.class.getClassLoader()一般用在getResource,因為你想要獲取某個資源文件的時候,這個資源文件的位置是相對固定的。

java的類加載機制(jvm規范)是委托模型,簡單的說,如果一個類加載器想要加載一個類,首先它會委托給它的parent去加載,如果它的所有parent都沒有成功的加載那么它才會自己親自來,有點兒像兒子使喚老子的感覺。。jvm也拼爹啊,,,,,
在jvm中默認有三類loaer,bootstrap,ext,app,其中boot最大是爺爺,app最小是孫子,ext中間是爹。
它們有權限訪問的classpath也不一樣,boot是jdk或jre下面的lib目錄,ext是jdk或jre的ext目錄,而app是由用戶指定的路徑,比如用-cp參數指定的目錄或jar。他們沒有權力訪問其他人的classpath,這樣問題就來鳥,,,,可能有人會問狗司令大人閑得蛋疼啊,搞這么復雜,據說是為了安全考慮,避免用戶的惡心意代碼侵蝕jvm,,問題就是當bootstrap或ext想要加載用戶指定classpath中的類就會失敗,因為這倆貨沒有權限訪問團app路徑中的類的,,所以就搞了這么一個不倫不類的contextloader。。。。


免責聲明!

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



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