国产一级a片免费看高清,亚洲熟女中文字幕在线视频,黄三级高清在线播放,免费黄色视频在线看

打開APP
userphoto
未登錄

開通VIP,暢享免費(fèi)電子書等14項(xiàng)超值服

開通VIP
ClassLoader 詳解及用途(寫的不錯)
ClassLoader主要對類的請求提供服務(wù),當(dāng)JVM需要某類時,它根據(jù)名稱向ClassLoader要求這個類,然后由ClassLoader返回這個類的class對象。 1.1 幾個相關(guān)概念ClassLoader負(fù)責(zé)載入系統(tǒng)的所有Resources(Class,文件,來自網(wǎng)絡(luò)的字節(jié)流等),通過ClassLoader從而將資源載入JVM  
每個class都有一個reference,指向自己的ClassLoader。Class.getClassLoader()  
array的ClassLoader就是其元素的ClassLoader,若是基本數(shù)據(jù)類型,則這個array沒有ClassLoader  
1.2 主要方法和工作過程Java1.1及從前版本中,ClassLoader主要方法:  
Class loadClass( String name, boolean resolve ); ClassLoader.loadClass() 是 ClassLoader 的入口點(diǎn)  
defineClass 方法是 ClassLoader 的主要訣竅。該方法接受由原始字節(jié)組成的數(shù)組并把它轉(zhuǎn)換成 Class 對象。原始數(shù)組包含如從文件系統(tǒng)或網(wǎng)絡(luò)裝入的數(shù)據(jù)。  
findSystemClass 方法從本地文件系統(tǒng)裝入文件。它在本地文件系統(tǒng)中尋找類文件,如果存在,就使用 defineClass 將原始字節(jié)轉(zhuǎn)換成 Class 對象,以將該文件轉(zhuǎn)換成類。當(dāng)運(yùn)行 Java 應(yīng)用程序時,這是 JVM 正常裝入類的缺省機(jī)制。  
resolveClass可以不完全地(不帶解析)裝入類,也可以完全地(帶解析)裝入類。當(dāng)編寫我們自己的 loadClass 時,可以調(diào)用 resolveClass,這取決于 loadClass 的 resolve 參數(shù)的值  
findLoadedClass 充當(dāng)一個緩存:當(dāng)請求 loadClass 裝入類時,它調(diào)用該方法來查看 ClassLoader 是否已裝入這個類,這樣可以避免重新裝入已存在類所造成的麻煩。應(yīng)首先調(diào)用該方法  
一般load方法過程如下:  

調(diào)用 findLoadedClass 來查看是否存在已裝入的類。  
如果沒有,那么采用某種特殊的神奇方式來獲取原始字節(jié)。(通過IO從文件系統(tǒng),來自網(wǎng)絡(luò)的字節(jié)流等)  
如果已有原始字節(jié),調(diào)用 defineClass 將它們轉(zhuǎn)換成 Class 對象。  
如果沒有原始字節(jié),然后調(diào)用 findSystemClass 查看是否從本地文件系統(tǒng)獲取類。  
如果 resolve 參數(shù)是 true,那么調(diào)用 resolveClass 解析 Class 對象。  
如果還沒有類,返回 ClassNotFoundException。  
否則,將類返回給調(diào)用程序。  
1.3 委托模型自從JDK1.2以后,ClassLoader做了改進(jìn),使用了委托模型,所有系統(tǒng)中的ClassLoader組成一棵樹,ClassLoader在載入類庫時先讓Parent尋找,Parent找不到才自己找。  
JVM在運(yùn)行時會產(chǎn)生三個ClassLoader,Bootstrap ClassLoader、Extension ClassLoader和App ClassLoader。其中,Bootstrap ClassLoader是用C++編寫的,在Java中看不到它,是null。它用來加載核心類庫,就是在lib下的類庫,Extension ClassLoader加載lib/ext下的類庫,App ClassLoader加載Classpath里的類庫,三者的關(guān)系為:App ClassLoader的Parent是Extension ClassLoader,而Extension ClassLoader的Parent為Bootstrap ClassLoader。加載一個類時,首先BootStrap進(jìn)行尋找,找不到再由Extension ClassLoader尋找,最后才是App ClassLoader。  

將ClassLoader設(shè)計(jì)成委托模型的一個重要原因是出于安全考慮,比如在Applet中,如果編寫了一個java.lang.String類并具有破壞性。假如不采用這種委托機(jī)制,就會將這個具有破壞性的String加載到了用戶機(jī)器上,導(dǎo)致破壞用戶安全。但采用這種委托機(jī)制則不會出現(xiàn)這種情況。因?yàn)橐虞djava.lang.String類時,系統(tǒng)最終會由Bootstrap進(jìn)行加載,這個具有破壞性的String永遠(yuǎn)沒有機(jī)會加載。  

委托模型還帶來了一些問題,在某些情況下會產(chǎn)生混淆,如下是Tomcat的ClassLoader結(jié)構(gòu)圖:  

                Bootstrap 
                  | 
                System 
                  | 
                Common 
                /     
            Catalina  Shared 
                      /     
                   Webapp1  Webapp2 ... 

由 Common 類裝入器裝入的類決不能(根據(jù)名稱)直接訪問由 Web 應(yīng)用程序裝入的類。使這些類聯(lián)系在一起的唯一方法是通過使用這兩個類集都可見的接口。在這個例子中,就是包含由 Java servlet 實(shí)現(xiàn)的 javax.servlet.Servlet。  
如果在lib或者lib/ext等類庫有與應(yīng)用中同樣的類,那么應(yīng)用中的類將無法被載入。通常在jdk新版本出現(xiàn)有類庫移動時會出現(xiàn)問題,例如最初我們使用自己的xml解析器,而在jdk1.4中xml解析器變成標(biāo)準(zhǔn)類庫,load的優(yōu)先級也高于我們自己的xml解析器,我們自己的xml解析器永遠(yuǎn)無法找到,將可能導(dǎo)致我們的應(yīng)用無法運(yùn)行。  

相同的類,不同的ClassLoader,將導(dǎo)致ClassCastException異常  

1.4 線程中的ClassLoader每個運(yùn)行中的線程都有一個成員contextClassLoader,用來在運(yùn)行時動態(tài)地載入其它類,可以使用方法Thread.currentThread().setContextClassLoader(...);更改當(dāng)前線程的contextClassLoader,來改變其載入類的行為;也可以通過方法Thread.currentThread().getContextClassLoader()來獲得當(dāng)前線程的ClassLoader。  
實(shí)際上,在Java應(yīng)用中所有程序都運(yùn)行在線程里,如果在程序中沒有手工設(shè)置過ClassLoader,對于一般的java類如下兩種方法獲得的ClassLoader通常都是同一個  

this.getClass.getClassLoader();  
Thread.currentThread().getContextClassLoader();  
方法一得到的Classloader是靜態(tài)的,表明類的載入者是誰;方法二得到的Classloader是動態(tài)的,誰執(zhí)行(某個線程),就是那個執(zhí)行者的Classloader。對于單例模式的類,靜態(tài)類等,載入一次后,這個實(shí)例會被很多程序(線程)調(diào)用,對于這些類,載入的Classloader和執(zhí)行線程的Classloader通常都不同。  

1.5 Web應(yīng)用中的ClassLoader回到上面的例子,在Tomcat里,WebApp的ClassLoader的工作原理有點(diǎn)不同,它先試圖自己載入類(在ContextPath/WEB-INF/...中載入類),如果無法載入,再請求父ClassLoader完成。  
由此可得:  

對于WEB APP線程,它的contextClassLoader是WebAppClassLoader  
對于Tomcat Server線程,它的contextClassLoader是CatalinaClassLoader  
1.6 獲得ClassLoader的幾種方法可以通過如下3種方法得到ClassLoader  
this.getClass.getClassLoader(); // 使用當(dāng)前類的ClassLoader  
Thread.currentThread().getContextClassLoader(); // 使用當(dāng)前線程的ClassLoader  
ClassLoader.getSystemClassLoader(); // 使用系統(tǒng)ClassLoader,即系統(tǒng)的入口點(diǎn)所使用的ClassLoader。(注意,system ClassLoader與根ClassLoader并不一樣。JVM下system ClassLoader通常為App ClassLoader)  
1.7 幾種擴(kuò)展應(yīng)用用戶定制自己的ClassLoader可以實(shí)現(xiàn)以下的一些應(yīng)用  
安全性。類進(jìn)入JVM之前先經(jīng)過ClassLoader,所以可以在這邊檢查是否有正確的數(shù)字簽名等  
加密。java字節(jié)碼很容易被反編譯,通過定制ClassLoader使得字節(jié)碼先加密防止別人下載后反編譯,這里的ClassLoader相當(dāng)于一個動態(tài)的解碼器  
歸檔??赡転榱斯?jié)省網(wǎng)絡(luò)資源,對自己的代碼做一些特殊的歸檔,然后用定制的ClassLoader來解檔  
自展開程序。把java應(yīng)用程序編譯成單個可執(zhí)行類文件,這個文件包含壓縮的和加密的類文件數(shù)據(jù),同時有一個固定的ClassLoader,當(dāng)程序運(yùn)行時它在內(nèi)存中完全自行解開,無需先安裝  
動態(tài)生成??梢陨蓱?yīng)用其他還未生成類的類,實(shí)時創(chuàng)建整個類并可在任何時刻引入JVM  
2.0 資源載入 
所有資源都通過ClassLoader載入到JVM里,那么在載入資源時當(dāng)然可以使用ClassLoader,只是對于不同的資源還可以使用一些別的方式載入,例如對于類可以直接new,對于文件可以直接做IO等。 2.1 載入類的幾種方法假設(shè)有類A和類B,A在方法amethod里需要實(shí)例化B,可能的方法有3種。對于載入類的情況,用戶需要知道B類的完整名字(包括包名,例如"com.rain.B")  
1. 使用Class靜態(tài)方法 Class.forName  

    Class cls = Class.forName("com.rain.B"); 
    B b = (B)cls.newInstance(); 

2. 使用ClassLoader  
    /* Step 1. Get ClassLoader */ 
    ClassLoader cl; // 如何獲得ClassLoader參考1.6 

    /* Step 2. Load the class */ 
    Class cls = cl.loadClass("com.rain.B"); // 使用第一步得到的ClassLoader來載入B 
     
    /* Step 3. new instance */ 
    B b = (B)cls.newInstance(); // 有B的類得到一個B的實(shí)例 

3. 直接new  
    B b = new B(); 

2.2 文件載入(例如配置文件等)假設(shè)在com.rain.A類里想讀取文件夾 /com/rain/config 里的文件sys.properties,讀取文件可以通過絕對路徑或相對路徑,絕對路徑很簡單,在Windows下以盤號開始,在Unix下以"/"開始  
對于相對路徑,其相對值是相對于ClassLoader的,因?yàn)镃lassLoader是一棵樹,所以這個相對路徑和ClassLoader樹上的任何一個ClassLoader相對比較后可以找到文件,那么文件就可以找到,當(dāng)然,讀取文件也使用委托模型  

1. 直接IO  

/** 
 * 假設(shè)當(dāng)前位置是 "C:/test",通過執(zhí)行如下命令來運(yùn)行A "java com.rain.A" 
 * 1. 在程序里可以使用絕對路徑,Windows下的絕對路徑以盤號開始,Unix下以"/"開始 
 * 2. 也可以使用相對路徑,相對路徑前面沒有"/" 
 * 因?yàn)槲覀冊?nbsp;"C:/test" 目錄下執(zhí)行程序,程序入口點(diǎn)是"C:/test",相對路徑就 
 * 是 "com/rain/config/sys.properties" 
 * (例子中,當(dāng)前程序的ClassLoader是App ClassLoader,system ClassLoader = 當(dāng)前的 
 * 程序的ClassLoader,入口點(diǎn)是"C:/test") 
 * 對于ClassLoader樹,如果文件在jdk lib下,如果文件在jdk lib/ext下,如果文件在環(huán)境變量里, 
 * 都可以通過相對路徑"sys.properties"找到,lib下的文件最先被找到 
 */ 
File f = new File("C:/test/com/rain/config/sys.properties"); // 使用絕對路徑 
//File f = new File("com/rain/config/sys.properties"); // 使用相對路徑 
InputStream is = new FileInputStream(f); 

如果是配置文件,可以通過java.util.Properties.load(is)將內(nèi)容讀到Properties里,Properties默認(rèn)認(rèn)為is的編碼是ISO-8859-1,如果配置文件是非英文的,可能出現(xiàn)亂碼問題。  
2. 使用ClassLoader  

/** 
 * 因?yàn)橛?種方法得到ClassLoader,對應(yīng)有如下3種方法讀取文件 
 * 使用的路徑是相對于這個ClassLoader的那個點(diǎn)的相對路徑,此處只能使用相對路徑 
 */ 
InputStream is = null; 
is = this.getClass().getClassLoader().getResourceAsStream( 
       "com/rain/config/sys.properties"); //方法1 
//is = Thread.currentThread().getContextClassLoader().getResourceAsStream( 
       "com/rain/config/sys.properties"); //方法2 
//is = ClassLoader.getSystemResourceAsStream("com/rain/config/sys.properties"); //方法3 

如果是配置文件,可以通過java.util.Properties.load(is)將內(nèi)容讀到Properties里,這里要注意編碼問題。  
3. 使用ResourceBundle  

    ResourceBundle bundle = ResourceBundle.getBoundle("com.rain.config.sys"); 

這種用法通常用來載入用戶的配置文件,關(guān)于ResourceBunlde更詳細(xì)的用法請參考其他文檔  
總結(jié):有如下3種途徑來載入文件  

    1. 絕對路徑 ---> IO 
    2. 相對路徑 ---> IO 
                ---> ClassLoader 
    3. 資源文件 ---> ResourceBundle 

2.3 如何在web應(yīng)用里載入資源在web應(yīng)用里當(dāng)然也可以使用ClassLoader來載入資源,但更常用的情況是使用ServletContext,如下是web目錄結(jié)構(gòu)  
    ContextRoot 
       |- JSP、HTML、Image等各種文件 
        |- [WEB-INF] 
              |- web.xml 
              |- [lib] Web用到的JAR文件 
                |- [classes] 類文件 

用戶程序通常在classes目錄下,如果想讀取classes目錄里的文件,可以使用ClassLoader,如果想讀取其他的文件,一般使用ServletContext.getResource()  

如果使用ServletContext.getResource(path)方法,路徑必須以"/"開始,路徑被解釋成相對于ContextRoot的路徑,此處載入文件的方法和ClassLoader不同,舉例"/WEB-INF/web.xml","/download/WebExAgent.rar"


轉(zhuǎn)自

http://blog.chinaunix.net/uid-21227800-id-65885.html


本站僅提供存儲服務(wù),所有內(nèi)容均由用戶發(fā)布,如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點(diǎn)擊舉報(bào)。
打開APP,閱讀全文并永久保存 查看更多類似文章
猜你喜歡
類似文章
getClass()和getClassLoader()區(qū)別 以及ClassLoader詳解及用途(文件加載,類加載)
getClass().getResourceAsStream()
Android中的動態(tài)加載機(jī)制
maven工程中讀取resource目錄下配置文件
路徑 服務(wù)器 getRealPath classLoader.getResource
Github Trending榜首|阿里開源Java在線診斷工具Arthas
更多類似文章 >>
生活服務(wù)
分享 收藏 導(dǎo)長圖 關(guān)注 下載文章
綁定賬號成功
后續(xù)可登錄賬號暢享VIP特權(quán)!
如果VIP功能使用有故障,
可點(diǎn)擊這里聯(lián)系客服!

聯(lián)系客服