您好,登錄后才能下訂單哦!
JVM中ClassLoader的示例分析,很多新手對此不是很清楚,為了幫助大家解決這個難題,下面小編將為大家詳細講解,有這方面需求的人可以來學習下,希望你能有所收獲。
前言:
了解JVM-類加載之前我們先了解下為什么要這樣? 學java 的都知道Java 是跨平臺語言,一套代碼到處運行,那為什么他可以跨平臺呢?
簡單的說下:之所以可以跨平臺運行 是依靠不同平臺的JVM,我們編寫代碼, javac 編譯成.class 文件,然后通過類加載器到JVM
內存之中,緊接著 Java解釋器將字節碼文件翻譯成機器代碼,執行并顯示結果,知道了前因后果 ,那我們來了解下 這個類加載器是怎么玩的呢?
稱述一些概念方便理解
字節碼文件是一種和任何具體機器環境及操作系統環境無關的中間代碼,它是一種二進制文件,是Java源文件由Java編譯器編譯后生成的目標代碼文件。編程人員和計算機都無法直接讀懂字節碼文件,它必須由專用的Java解釋器來解釋執行,因此Java是一種在編譯基礎上進行解釋運行的語言。
Java解釋器負責將字節碼文件翻譯成具體硬件環境和操作系統平臺下的機器代碼,以便執行。因此Java程序不能直接運行在現有的操作系統平臺上,它必須運行在被稱為Java虛擬機的軟件平臺之上。
完整的過程如下,圖片來源于網絡
了解了大體概貌我們接著去了解細節!
1.什么是類加載?
通俗的講就是將編譯后的.class 加載到內存,經過類加載器處理之后成為可以被虛擬機直接使用的
數據, .class 文件類加載之后在jvm中形成一份描述Class 結構的元信息對象,通過該元信息可以知道
class的結構信息:如構造函數,屬性和方法等,Java允許用戶借由這個Class相關的元信息對象
間接調用Class對象的功能,這里就是我們經常能見到的Class類。
2. 類加載過程
類加載完畢結果如圖
3. 類加載器
Java類加載器是一部分的Java運行時環境可以動態加載Java類到Java虛擬機。由于類加載器的原因,Java運行時系統不需要了解文件和文件系統。
Java類不會一次全部加載到內存中,而是在應用程序需要時加載。此時,JRE將調用Java ClassLoader,并且這些ClassLoader將類動態加載到內存中。
并非所有類都由單個ClassLoader加載。根據類的類型和類的路徑,決定加載該特定類的ClassLoader。要了解加載類的ClassLoader,請使用getClassLoader()方法。所有類均基于其名稱進行加載,如果未找到這些類中的任何一個,則它將返回NoClassDefFoundError或ClassNotFoundException。
1. Java Classloader具有以下三種類型:
1.BootStrap類加載器: Bootstrap類加載器是一種機器代碼,當JVM調用它時會啟動操作。它不是一個Java類。它的工作是加載第一個純Java ClassLoader。Bootstrap ClassLoader從rt.jar位置加載類。Bootstrap ClassLoader沒有任何父ClassLoader。也稱為Primodial ClassLoader。
2.擴展ClassLoader:擴展ClassLoader是Bootstrap ClassLoader的子級,并從相應的JDK擴展庫中加載核心Java類的擴展。它從jre / lib / ext目錄或系統屬性java.ext.dirs指向的任何其他目錄中加載文件。
3.系統類加載器:應用程序類加載器也稱為系統類加載器。它加載在環境變量CLASSPATH,-classpath或-cp命令行選項中找到的應用程序類型類。Application ClassLoader是Extension ClassLoader的子類。
注意:ClassLoader委托層次結構模型始終按Application ClassLoader-> Extension ClassLoader-> Bootstrap ClassLoader的順序運行。始終給Bootstrap ClassLoader更高的優先級,其次是Extension ClassLoader,然后是Application ClassLoader。
2 Java ClassLoader有功能性三個原則,它們是:
1.委托模型:Java虛擬機和Java ClassLoader使用一種稱為“ 委托層次算法”的算法將類加載到Java文件中。
ClassLoader基于委托模型提供的一組操作進行工作。他們是:
ClassLoader始終遵循委托層次結構原則。
每當JVM遇到一個類時,它都會檢查該類是否已加載。
如果該類已經在方法區域中加載,則JVM繼續執行。
如果該類不在方法區域中,則JVM要求Java ClassLoader子系統加載該特定類,然后ClassLoader子系統將控件移交給Application ClassLoader。
然后,應用程序ClassLoader將請求委托給Extension ClassLoader,而Extension ClassLoader依次將請求委托給Bootstrap ClassLoader。
Bootstrap ClassLoader將在Bootstrap類路徑(JDK / JRE / LIB)中搜索。如果該類可用,則將其加載,否則將請求委托給Extension ClassLoader。
Extension ClassLoader在擴展類路徑(JDK / JRE / LIB / EXT)中搜索類。如果該類可用,則將其加載,否則將請求委托給Application ClassLoader。
Application ClassLoader在應用程序類路徑中搜索該類。如果該類可用,則將其加載,否則,將生成ClassNotFoundException異常。
2.可見性原則:可見性原則指出,父ClassLoader加載的類對子ClassLoader可見,但子ClassLoader加載的類對父 ClassLoader不可見。假設擴展類加載器已加載了GEEKS.class類,則該類僅對擴展類加載器和應用程序類加載器可見, 而對引導類加載器不可見。如果再次嘗試使用Bootstrap ClassLoader加載該類,它將給出異常java.lang.ClassNotFoundException。
3.Uniqueness 屬性:Uniquesness屬性可確保類是唯一的,并且不會重復類。這還確保了由父類加載器加載的類不會由子類加載器加載。如果父類加載器無法找到該類,則只有當前實例自己會嘗試這樣做。
Java.lang.ClassLoader的方法
在JVM請求該類之后,將遵循一些步驟以加載一個類。按照委托模型加載類,但是有一些重要的方法或函數在加載類中起著至關重要的作用。
loadClass(String name,boolean resolve):此方法用于加載JVM引用的類。它以類的名稱為參數。類型為loadClass(String,boolean)。
defineClass():defineClass()方法是最終方法,不能被覆蓋。此方法用于將字節數組定義為class的實例。如果該類無效,則拋出ClassFormatError。
findClass(String name):此方法用于查找指定的類。此方法僅查找但不加載類。
findLoadedClass(String name):此方法用于驗證JVM引用的Class是否先前已加載。
Class.forName(String name,boolean initialize,ClassLoader loader):此方法用于加載類以及初始化類。此方法還提供選擇任何一個ClassLoader的選項。如果ClassLoader參數為NULL,則使用Bootstrap ClassLoader。
示例:在加載類之前執行以下代碼:
protected synchronized Class<?>
loadClass(String name, boolean resolve)
throws ClassNotFoundException
{
Class c = findLoadedClass(name);
try {
if (c == NULL) {
if (parent != NULL) {
c = parent.loadClass(name, false);
}
else {
c = findBootstrapClass0(name);
}
}
catch (ClassNotFoundException e)
{
System.out.println(e);
}
}
}
注意:如果已經加載了一個類,它將返回它。否則,它將對新類的搜索委托給父類加載器。如果父類加載器找不到該類,則loadClass()調用方法findClass()來查找和加載該類。
看完上述內容是否對您有幫助呢?如果還想對相關知識有進一步的了解或閱讀更多相關文章,請關注億速云行業資訊頻道,感謝您對億速云的支持。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。