Classloader和線程

 Java中所有的類都是由classloader進行加載的。

通常情況下我們不需要顯式的去使用類加載器。

但是對於一個web容器而言,通常擁有多個classloader,我們知道,每個classloader所加載的類彼此都是不可見的。比如一個servlet程序,它使用了WEB-INF/lib下面的log4j,而tomcat本身也有一套logj的包。顯然對於servlet而言,它是看不到tomcat的log4j,反之亦然。

這一點如何做到?
答案就是線程自身的contextClassLoader。我們知道java代碼總是在某個線程中執行的,這個線程所需要的類,則是由它自己的contextClassLoader所加載;當一個線程開啓了一個子線程,則子線程會隱式的繼承父線程的classloader。這個就是類加載器隔離的關鍵。

我們可以很容易寫一小段代碼來證實:
下面這段代碼運行後輸出是,

main_cl:sun.misc.Launcher$AppClassLoader@1a46e30
MainProc:org.kevx.MyClassLoader@1fb8ee3
SubProc:org.kevx.MyClassLoader@1fb8ee3

證明了上面這個結論。

 

  1. class MainProc implements Runnable { 
  2.       @Override 
  3.       public void run() { 
  4.              out.println( "MainProc:" + Thread.currentThread().getContextClassLoader()); 
  5.              new Thread( new SubProc()).start(); 
  6.       } 
  7.  
  8. class SubProc implements Runnable { 
  9.       @Override 
  10.       public void run() { 
  11.              out.println( "SubProc:" + Thread.currentThread().getContextClassLoader()); 
  12.       } 
  13.  
  14. class MyClassLoader extends URLClassLoader { 
  15.       public MyClassLoader(URL[] urls) { 
  16.              super(urls); 
  17.       } 
  18.  
  19. public class AsciiUtil { 
  20.        
  21.       public static void main(String[] args) throws Exception { 
  22.              out.println( "main_cl:" + Thread.currentThread().getContextClassLoader()); 
  23.              
  24.             URL url = new URL( "file:///c:/Program Files/Java/jre6/lib" ); 
  25.             MyClassLoader mcl = new MyClassLoader( new URL[]{url}); 
  26.             Thread. currentThread().setContextClassLoader(mcl); 
  27.              
  28.              new Thread( new MainProc()).start(); 
  29.       } 
  30.  
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章