類加載器的資料,以後備用


  一、Class是怎麼被加載的? 
  每個Class對象都保留着加載自己的類加載器的引用,可以通過Class對象的getClassLoader方法來獲得其引用。ClassLoader通過loadClass方法來加載這個類。 
  一般來說,loadClass方法的實現邏輯是這樣的: 
  1.該類如果被加載過,則直接返回以前加載過的Class對象;否則繼續下一步; 
  2.調用findClass把類名對應的字節碼文件解析成字節數組。 
  3.調用defineClass將字節數組解析成爲class對象,該方法是native方法,完成了解析字節碼文件的工作。 
  由此看來,如果我們想實現自己的類加載器(比如,通過網絡加載遠程的字節碼文件),那麼就需要重寫findClass方法來完成。 

  二、類加載器的類型 
  Java的系統類加載器有三種類型: 
  1.bootstrap classloader:用於加載核心類庫(java.*) 
  2.extension classloader:用於加載擴展類庫(javax.*) 
  3.system classloader:用於加載我們自己寫的類,當然也包括我們用到的類庫。 

  三、Parent-First & Child-First 
  每個ClassLoader(? extends ClassLoader)都有它的父加載器,可以通過ClassLoader的getParent方法獲得。可以看的出來,樹的根就是bootstrap classloader。當我們要自定義一個類加載器的時候,首先需要考慮的問題就是先讓父類加載器去加載還是先自己加載,所以就有了Parent-First和Child-First。ClassLoader的默認實現就是Parent-First,這也是最常見的實現方式。 

  四、ContextClassLoader 
  通常來說我們不會實現自己的ClassLoader,但這並不代表我們沒有用到過自定義的ClassLoader。commons-logging裏的這篇文章提供了一個非常好的例子。 
  一般來說Web容器會開啓一個線程池來接受處理Http請求,找到處理該請求的Web app,然後交給它處理。Web容器裏是可以跑多個應用的,那麼,想象一下,這多個應用都是通過同一個類加載器(也就是加載Web容器的類加載器)加載的嗎?顯然不是,因爲如果是這樣的話,那麼Web應用之間就是透明的了。實際情況顯然不是這樣的。 
  實際的情況是,在Web容器剛啓動時,會啓動Web容器類加載器來加載Web容器,然後爲每個應用創建派生自Web容器的類加載器去加載Web應用。這樣的話,Web應用能訪問到Web容器的資源(比如說,Web容器的類庫),但他們之間卻是隔離的。 
  從Java1.2之後,Java提供了一個新的ClassLoader:context classloader。context classloader是與線程綁在一起的,可以通過Thread的setContextLoader進行設置,通過getContextLoader來獲得。回到之前的那個場景,當Web容器接受到Http請求,它會將加載Web容器的ClassLoader與這個線程關聯起來,當Web容器完成了前期工作,需要將Http請求交給Web應用,跨過應用程序邊界(cross the application boundary)時,Web容器會將加載處理請求的Web應用的ClassLoader與這個線程關聯起來。當Web應用處理完請求,又交還給Web容器時,Web容器再次將context classloader設回加載Web容器的ClassLoader。 

類加載器的資料,以後備用

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章