類加載器


ClassLoad:類加載器(class loader)用來加載 Java 類到 Java 虛擬機中。Java 源程序(.java 文件)在經過 Java 編譯器編譯之後就被轉換成 Java 字節代碼(.class 文件)。類加載器負責讀取 Java 字節代碼,並轉換成 java.lang.Class 類的一個實例。

類加載機制
記載,驗證,準備,解析,初始化,使用,卸載

類加載器分爲三個
Bootstrp loader,ExtClassLoader,AppClassLoader
Bootstrp loader:主要加載 jre/lib 、jre/class 、-Xbootclasspath參數指定的路徑

那麼爲什麼三個類加載器呢?因爲它們代表三個層次的信任。最值得信任的類是核心API類。接下來是已安裝的擴展,然後是類路徑中顯示的類,這意味着它們是您的計算機的本地。


ExtClassLoader:ExtClassLoader由Bootstrp loader加載,並將ExtClassLoader的父加載器設置爲Bootstrp loader,主要加載jre/lib/ext下的類庫

AppClassLoader :Bootstrp loader加載完ExtClassLoader後,就會加載AppClassLoader,並將ClassLoader父加載器指定爲ExtClassLoader,ClassLoader有個方法getSystemClassLoader,此方法返回的正式AppClassLoader.AppClassLoader主要負責加載Classpath所指定的位置的類

在java中類加載器把一個類裝入JVM經過以下步驟
1.查找和導入class文件 2,檢查class文件的正確性 3.給類的靜態變量分配空間 3,將符號應用轉換爲直接引用 4.對靜態變量和靜態代碼塊執行初始化工作

Java裝載類使用“全盤負責委託機制”。
“全盤負責”是指當一個classLoader加載一個類時,該類所依賴及引用的類也由當前classLoader加載
“委託機制”是指,類加載器加載一個類時先會委託父類尋找目標類,只有在找不到的情況下才會從自己的類路徑中查找並裝在目標類。這一點是從安全方面考慮的,試想如果一個人寫了一個惡意的基礎類(如java.lang.String)並加載到JVM將會引起嚴重的後果,但有了全盤負責制,java.lang.String永遠是由根裝載器來裝載,避免以上情況發生

爲什麼要使用這種雙親委託模式呢?
1、避免重複加載,父classLoader已經加載了該類時,子classLoader就沒有必要再加載一次
2、安全因素。我們試想一下,如果不使用這種委託模式,那我們就可以隨時使用自定義的String來動態替代java核心api中定義類型,這樣會存在非常大的安全隱患,而雙親委託的方式,就可以避免這種情況,因爲String已經在啓動時被加載,所以用戶自定義類是無法加載一個自定義的ClassLoader。


既然JVM已經提供了默認的類加載器,爲什麼還要定義自已的類加載器呢?
 
因爲Java中提供的默認ClassLoader,只加載指定目錄下的jar和class,如果我們想加載其它位置的類或jar時,比如:我要加載網絡上的一個class文件,通過動態加載到內存之後,要調用這個類中的方法實現我的業務邏輯。在這樣的情況下,默認的ClassLoader就不能滿足我們的需求了,所以需要定義自己的ClassLoader。

定義自已的類加載器分爲兩步: 
1、繼承java.lang.ClassLoader
2、重寫父類的findClass方法

類加載器與web容器
對於運行在 Java EE容器中的 Web 應用來說,類加載器的實現方式與一般的java應用有所不同,每個web應用都有一個對應的加載器實例。以Tomcat來說,每個應用都對應一個類加載器實例,該加載器實例不同的是它首先嚐試加載某個類,如果找不到再代理給父類加載器。這與java應用的加載器順序是相反的。這個是java servlet規範中推薦的做飯,其目的是使得web應用自己的類的優先級高於web容器提供的類。這種代理模式的一個例外是:Java 核心庫的類是不在查找範圍之內的。這也是爲了保證 Java 核心庫的類型安全。

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