類加載器的資料,以後備用
一、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。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.