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

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

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

 

忘記之前有沒有問過這個問題,總之我如今有看到幾個地方有這個:
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

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。。。。apache

相關文章
相關標籤/搜索