1. 程式人生 > >ClassLoader 詳解及用途(寫的不錯)

ClassLoader 詳解及用途(寫的不錯)

ClassLoader主要對類的請求提供服務,當JVM需要某類時,它根據名稱向ClassLoader要求這個類,然後由ClassLoader返回這個類的class物件。 1.1 幾個相關概念ClassLoader負責載入系統的所有Resources(Class,檔案,來自網路的位元組流等),通過ClassLoader從而將資源載入JVM  
每個class都有一個reference,指向自己的ClassLoader。Class.getClassLoader()  
array的ClassLoader就是其元素的ClassLoader,若是基本資料型別,則這個array沒有ClassLoader  

1.2 主要方法和工作過程Java1.1及從前版本中,ClassLoader主要方法:  
Class loadClass( String name, boolean resolve ); ClassLoader.loadClass() 是 ClassLoader 的入口點  
defineClass 方法是 ClassLoader 的主要訣竅。該方法接受由原始位元組組成的陣列並把它轉換成 Class 物件。原始陣列包含如從檔案系統或網路裝入的資料。  
findSystemClass 方法從本地檔案系統裝入檔案。它在本地檔案系統中尋找類檔案,如果存在,就使用 defineClass 將原始位元組轉換成 Class 物件,以將該檔案轉換成類。當執行 Java 應用程式時,這是 JVM 正常裝入類的預設機制。  

resolveClass可以不完全地(不帶解析)裝入類,也可以完全地(帶解析)裝入類。當編寫我們自己的 loadClass 時,可以呼叫 resolveClass,這取決於 loadClass 的 resolve 引數的值  
findLoadedClass 充當一個快取:當請求 loadClass 裝入類時,它呼叫該方法來檢視 ClassLoader 是否已裝入這個類,這樣可以避免重新裝入已存在類所造成的麻煩。應首先呼叫該方法  
一般load方法過程如下:  

呼叫 findLoadedClass 來檢視是否存在已裝入的類。  
如果沒有,那麼採用某種特殊的神奇方式來獲取原始位元組。(通過IO從檔案系統,來自網路的位元組流等)  

如果已有原始位元組,呼叫 defineClass 將它們轉換成 Class 物件。  
如果沒有原始位元組,然後呼叫 findSystemClass 檢視是否從本地檔案系統獲取類。  
如果 resolve 引數是 true,那麼呼叫 resolveClass 解析 Class 物件。  
如果還沒有類,返回 ClassNotFoundException。  
否則,將類返回給呼叫程式。  
1.3 委託模型自從JDK1.2以後,ClassLoader做了改進,使用了委託模型,所有系統中的ClassLoader組成一棵樹,ClassLoader在載入類庫時先讓Parent尋找,Parent找不到才自己找。  
JVM在執行時會產生三個ClassLoader,Bootstrap ClassLoader、Extension ClassLoader和App ClassLoader。其中,Bootstrap ClassLoader是用C++編寫的,在Java中看不到它,是null。它用來載入核心類庫,就是在lib下的類庫,Extension ClassLoader載入lib/ext下的類庫,App ClassLoader載入Classpath裡的類庫,三者的關係為:App ClassLoader的Parent是Extension ClassLoader,而Extension ClassLoader的Parent為Bootstrap ClassLoader。載入一個類時,首先BootStrap進行尋找,找不到再由Extension ClassLoader尋找,最後才是App ClassLoader。  

將ClassLoader設計成委託模型的一個重要原因是出於安全考慮,比如在Applet中,如果編寫了一個java.lang.String類並具有破壞性。假如不採用這種委託機制,就會將這個具有破壞性的String載入到了使用者機器上,導致破壞使用者安全。但採用這種委託機制則不會出現這種情況。因為要載入java.lang.String類時,系統最終會由Bootstrap進行載入,這個具有破壞性的String永遠沒有機會載入。  

委託模型還帶來了一些問題,在某些情況下會產生混淆,如下是Tomcat的ClassLoader結構圖:  

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

由 Common 類裝入器裝入的類決不能(根據名稱)直接訪問由 Web 應用程式裝入的類。使這些類聯絡在一起的唯一方法是通過使用這兩個類集都可見的介面。在這個例子中,就是包含由 Java servlet 實現的 javax.servlet.Servlet。  
如果在lib或者lib/ext等類庫有與應用中同樣的類,那麼應用中的類將無法被載入。通常在jdk新版本出現有類庫移動時會出現問題,例如最初我們使用自己的xml解析器,而在jdk1.4中xml解析器變成標準類庫,load的優先順序也高於我們自己的xml解析器,我們自己的xml解析器永遠無法找到,將可能導致我們的應用無法執行。  

相同的類,不同的ClassLoader,將導致ClassCastException異常  

1.4 執行緒中的ClassLoader每個執行中的執行緒都有一個成員contextClassLoader,用來在執行時動態地載入其它類,可以使用方法Thread.currentThread().setContextClassLoader(...);更改當前執行緒的contextClassLoader,來改變其載入類的行為;也可以通過方法Thread.currentThread().getContextClassLoader()來獲得當前執行緒的ClassLoader。  
實際上,在Java應用中所有程式都執行線上程裡,如果在程式中沒有手工設定過ClassLoader,對於一般的java類如下兩種方法獲得的ClassLoader通常都是同一個  

this.getClass.getClassLoader();  
Thread.currentThread().getContextClassLoader();  
方法一得到的Classloader是靜態的,表明類的載入者是誰;方法二得到的Classloader是動態的,誰執行(某個執行緒),就是那個執行者的Classloader。對於單例模式的類,靜態類等,載入一次後,這個例項會被很多程式(執行緒)呼叫,對於這些類,載入的Classloader和執行執行緒的Classloader通常都不同。  

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

對於WEB APP執行緒,它的contextClassLoader是WebAppClassLoader  
對於Tomcat Server執行緒,它的contextClassLoader是CatalinaClassLoader  
1.6 獲得ClassLoader的幾種方法可以通過如下3種方法得到ClassLoader  
this.getClass.getClassLoader(); // 使用當前類的ClassLoader  
Thread.currentThread().getContextClassLoader(); // 使用當前執行緒的ClassLoader  
ClassLoader.getSystemClassLoader(); // 使用系統ClassLoader,即系統的入口點所使用的ClassLoader。(注意,system ClassLoader與根ClassLoader並不一樣。JVM下system ClassLoader通常為App ClassLoader)  
1.7 幾種擴充套件應用使用者定製自己的ClassLoader可以實現以下的一些應用  
安全性。類進入JVM之前先經過ClassLoader,所以可以在這邊檢查是否有正確的數字簽名等  
加密。java位元組碼很容易被反編譯,通過定製ClassLoader使得位元組碼先加密防止別人下載後反編譯,這裡的ClassLoader相當於一個動態的解碼器  
歸檔。可能為了節省網路資源,對自己的程式碼做一些特殊的歸檔,然後用定製的ClassLoader來解檔  
自展開程式。把java應用程式編譯成單個可執行類檔案,這個檔案包含壓縮的和加密的類檔案資料,同時有一個固定的ClassLoader,當程式執行時它在記憶體中完全自行解開,無需先安裝  
動態生成。可以生成應用其他還未生成類的類,實時建立整個類並可在任何時刻引入JVM  
2.0 資源載入 
所有資源都通過ClassLoader載入到JVM裡,那麼在載入資源時當然可以使用ClassLoader,只是對於不同的資源還可以使用一些別的方式載入,例如對於類可以直接new,對於檔案可以直接做IO等。 2.1 載入類的幾種方法假設有類A和類B,A在方法amethod裡需要例項化B,可能的方法有3種。對於載入類的情況,使用者需要知道B類的完整名字(包括包名,例如"com.rain.B")  
1. 使用Class靜態方法 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的例項 

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

2.2 檔案載入(例如配置檔案等)假設在com.rain.A類裡想讀取資料夾 /com/rain/config 裡的檔案sys.properties,讀取檔案可以通過絕對路徑或相對路徑,絕對路徑很簡單,在Windows下以盤號開始,在Unix下以"/"開始  
對於相對路徑,其相對值是相對於ClassLoader的,因為ClassLoader是一棵樹,所以這個相對路徑和ClassLoader樹上的任何一個ClassLoader相對比較後可以找到檔案,那麼檔案就可以找到,當然,讀取檔案也使用委託模型  

1. 直接IO  

/** 
 * 假設當前位置是 "C:/test",通過執行如下命令來執行A "java com.rain.A" 
 * 1. 在程式裡可以使用絕對路徑,Windows下的絕對路徑以盤號開始,Unix下以"/"開始 
 * 2. 也可以使用相對路徑,相對路徑前面沒有"/" 
 * 因為我們在 "C:/test" 目錄下執行程式,程式入口點是"C:/test",相對路徑就 
 * 是 "com/rain/config/sys.properties" 
 * (例子中,當前程式的ClassLoader是App ClassLoader,system ClassLoader = 當前的 
 * 程式的ClassLoader,入口點是"C:/test") 
 * 對於ClassLoader樹,如果檔案在jdk lib下,如果檔案在jdk lib/ext下,如果檔案在環境變數裡, 
 * 都可以通過相對路徑"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)將內容讀到Properties裡,Properties預設認為is的編碼是ISO-8859-1,如果配置檔案是非英文的,可能出現亂碼問題。  
2. 使用ClassLoader  

/** 
 * 因為有3種方法得到ClassLoader,對應有如下3種方法讀取檔案 
 * 使用的路徑是相對於這個ClassLoader的那個點的相對路徑,此處只能使用相對路徑 
 */ 
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)將內容讀到Properties裡,這裡要注意編碼問題。  
3. 使用ResourceBundle  

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

這種用法通常用來載入使用者的配置檔案,關於ResourceBunlde更詳細的用法請參考其他文件  
總結:有如下3種途徑來載入檔案  

    1. 絕對路徑 ---> IO 
    2. 相對路徑 ---> IO 
                ---> ClassLoader 
    3. 資原始檔 ---> ResourceBundle 

2.3 如何在web應用裡載入資源在web應用裡當然也可以使用ClassLoader來載入資源,但更常用的情況是使用ServletContext,如下是web目錄結構  
    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"

轉自

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

相關推薦

ClassLoader 用途(不錯)

ClassLoader主要對類的請求提供服務,當JVM需要某類時,它根據名稱向ClassLoader要求這個類,然後由ClassLoader返回這個類的class物件。 1.1 幾個相關概念ClassLoader負責載入系統的所有Resources(Class,檔案,來自網

Classloader用途

寫的很不錯,轉載以供大家參考 ClassLoader主要對類的請求提供服務,當JVM需要某類時,它根據名稱向ClassLoader要求這個類,然後由ClassLoader返回 這個類的class物件。 1.1 幾個相關概念ClassLoader負責載入系統的所有Resou

getClass()和getClassLoader()區別 以及ClassLoader用途(檔案載入,類載入)

 1.1 幾個相關概念ClassLoader負責載入系統的所有Resources(Class,檔案,來自網路的位元組流等),通過ClassLoader從而將資源載入JVM   每個class都有一個reference,指向自己的ClassLoader。Class.getClassLoader()   arra

Android檔案儲存的問題:ClassLoader和實現Parcelable介面後 用途

可能小夥伴們讀了我上一篇部落格關於Android檔案儲存的的,在檔案操作的時候大家有沒有疑問呀,有就對了,可能在儲存自定義物件的時候,如何序列化呀?ClassLoader到底是啥鬼呀?序列化後怎麼讀取出來呀?好吧,針對於上面的問題,我一個一個的說明吧! 今天主

搬家行業開發小程序系統(App.Config操作)

設置 反饋 流程 選擇 文件的 搬家 功能 操作 服務項目 應用程序配置文件是標準的 XML 文件,XML 標記和屬性是區分大小寫的。它是可以按需要更改的,開發人員可以使用配置文件來更改設置,而不必重編譯應用程序。配置文件的根節點是configuration。我們經常訪問的

sqlserver約束用途

SQL的主鍵和外來鍵的作用: 外來鍵取值規則:空值或參照的主鍵值。 (1)插入非空值時,如果主鍵表中沒有這個值,則不能插入。 (2)更新時,不能改為主鍵表中沒有的值。 (3)刪除主鍵表記錄時,你可以在建外來鍵時選定外來鍵記錄一起級聯刪除還是拒絕刪除。 (4)更新

SQL的主鍵和外來鍵約束用途

SQL的主鍵和外來鍵的作用: 外來鍵取值規則:空值或參照的主鍵值。 (1)插入非空值時,如果主鍵表中沒有這個值,則不能插入。 (2)更新時,不能改為主鍵表中沒有的值。 (3)刪除主鍵表記錄時,你可以在建外來鍵時選定外來鍵記錄一起級聯刪除還是拒絕刪除。 (4)更新主鍵記錄時

MANIFEST.MF的用途

Manifest-Version: 1.0Created-By: Apache Ant 1.5.1Extension-Name: Struts FrameworkSpecification-Title: Struts FrameworkSpecification-Vendor: Apache Software

java中的vector用途

Vector 類 提 供 了 實 現 可 增 長 數 組 的 功 能, 隨 著 更 多 元 素 加 入 其 中, 數 組 變 的 更 大。 在 刪 除 一 些 元 素 之 後, 數 組 變 小。 Vector 有 三 個 構 造 函 數, public Vector

(read&write)視訊(video) 程式碼

讀取(read&write)視訊(video) 詳解 及 程式碼本文地址: http://blog.csdn.net/caroline_wendy/article/details/1708439

IOS 檔案讀操作簡單例項

iPhone 檔案讀寫操作1,寫檔案操作- (IBAction)btnWrite:(id)sender { //建立檔案管理器 NSFileManager *fileManager = [NSFileManager defaultManager]; //獲取路徑

ClassLoader

normal class對象 logs 目錄 left 進行 family lib 時間 1. classLoader是什麽? ClassLoader是類的加載器,用於加載class對象到JVM中的,分為2種,啟動類加載器和實際類加載器. 2. ClassLoader的作

DELL EqualLogic PS6100存儲數據恢復解決辦法

存儲 數據 恢復 DELL EqualLogic PS6100采用虛擬ISCSI SAN陣列,為遠程或分支辦公室、部門和中小企業存儲部署帶來企業級功能、智能化、自動化和可靠性,支持VMware、Solaris、Linux、Mac、HPux、AIX,支持所有帶有業界標準iscsi initiator的操作系

Js中JSON.stringify()與JSON.parse()與eval()使用案例

div 網絡 blog 處理 ive asc 還要 ava 不同 JSON(JavaScript Object Notation)是一種輕量級的數據交換格式。因為采用獨立於語言的文本格式,也使用了類似於C語言家族的習慣,擁有了這些特性使使JSON稱為理想的數據交換語言,作用

JS函數動作分層結構Document.getElementById 釋義 事件 函數 變量 script標簽 var function

src 分層 鼠標 靜態頁面 font 編寫 技術分享 對話 fun html +css 靜態頁面 js 動態 交互 原理: js就是修改樣式, 比如彈出一個對話框. 彈出的過程就是這個框由disable 變成display:enable. 又或者當鼠標指

AngularJS 過濾與排序實例代碼

highlight 進行 angularjs ngs key 管道命令 個數 變量 數據 這篇文章主要介紹了AngularJS 過濾與排序,實現查詢過濾以及排序的功能。 通過這篇文章可以了解到   1、 angularjs的過濾器   2、 ng-repeat的使用方法

Git服務器安裝安裝遇到問題解決方案【轉】

bsp erb 倉庫 .... gnu libcurl 執行 body ebs 轉自:http://www.cnblogs.com/grimm/p/5368777.html git是一個不錯的版本管理的工具。現在自己在搞一個簡單的應用程序開發,想使用git來進行管理。

增強for循環的使用代碼

str 使用詳解 對象 示例 -c int tty 語法 使用 首先說一下他的語法結構: for(數據類型 變量 :集合){ //這裏寫要遍歷的元素,或者所需要的代碼即可//如果集合中存放的是對象,可以獲取到每個對象(數據類型=對象類型 變量(遍歷出來的每個對

SQL update select結合語句應用

應用 comm 執行 sel ron 詳解 strong 閱讀 等於 SQL update select結合語句詳解及應用 2013年10月1日 MK 數據庫 19 閱讀 157639次 QL update select語句 最常用的update語法是: 1 2

WebService中的WSDL jmeter測試

images 包括 3.2 接口測試工具 types 通知 操作 sdl message 首先簡單講解一下什麽是wsdl. 一個WSDL文檔通常包含8個重要的元素,即definitions、types、import、message、portType、ope