JVM中ClassLoader的示例分析,很多新手對此不是很清楚,為了幫助大家解決這個難題,下面小編將為大家詳細(xì)講解,有這方面需求的人可以來學(xué)習(xí)下,希望你能有所收獲。
公司主營業(yè)務(wù):成都網(wǎng)站設(shè)計、成都做網(wǎng)站、移動網(wǎng)站開發(fā)等業(yè)務(wù)。幫助企業(yè)客戶真正實現(xiàn)互聯(lián)網(wǎng)宣傳,提高企業(yè)的競爭能力。成都創(chuàng)新互聯(lián)是一支青春激揚、勤奮敬業(yè)、活力青春激揚、勤奮敬業(yè)、活力澎湃、和諧高效的團隊。公司秉承以“開放、自由、嚴(yán)謹(jǐn)、自律”為核心的企業(yè)文化,感謝他們對我們的高要求,感謝他們從不同領(lǐng)域給我們帶來的挑戰(zhàn),讓我們激情的團隊有機會用頭腦與智慧不斷的給客戶帶來驚喜。成都創(chuàng)新互聯(lián)推出扶溝免費做網(wǎng)站回饋大家。
前言:
了解JVM-類加載之前我們先了解下為什么要這樣? 學(xué)java 的都知道Java 是跨平臺語言,一套代碼到處運行,那為什么他可以跨平臺呢?
簡單的說下:之所以可以跨平臺運行 是依靠不同平臺的JVM,我們編寫代碼, javac 編譯成.class 文件,然后通過類加載器到JVM
內(nèi)存之中,緊接著 Java解釋器將字節(jié)碼文件翻譯成機器代碼,執(zhí)行并顯示結(jié)果,知道了前因后果 ,那我們來了解下 這個類加載器是怎么玩的呢?
稱述一些概念方便理解
字節(jié)碼文件是一種和任何具體機器環(huán)境及操作系統(tǒng)環(huán)境無關(guān)的中間代碼,它是一種二進制文件,是Java源文件由Java編譯器編譯后生成的目標(biāo)代碼文件。編程人員和計算機都無法直接讀懂字節(jié)碼文件,它必須由專用的Java解釋器來解釋執(zhí)行,因此Java是一種在編譯基礎(chǔ)上進行解釋運行的語言。
Java解釋器負(fù)責(zé)將字節(jié)碼文件翻譯成具體硬件環(huán)境和操作系統(tǒng)平臺下的機器代碼,以便執(zhí)行。因此Java程序不能直接運行在現(xiàn)有的操作系統(tǒng)平臺上,它必須運行在被稱為Java虛擬機的軟件平臺之上。
完整的過程如下,圖片來源于網(wǎng)絡(luò)
了解了大體概貌我們接著去了解細(xì)節(jié)!
1.什么是類加載?
通俗的講就是將編譯后的.class 加載到內(nèi)存,經(jīng)過類加載器處理之后成為可以被虛擬機直接使用的
數(shù)據(jù), .class 文件類加載之后在jvm中形成一份描述Class 結(jié)構(gòu)的元信息對象,通過該元信息可以知道
class的結(jié)構(gòu)信息:如構(gòu)造函數(shù),屬性和方法等,Java允許用戶借由這個Class相關(guān)的元信息對象
間接調(diào)用Class對象的功能,這里就是我們經(jīng)常能見到的Class類。
2. 類加載過程
類加載完畢結(jié)果如圖
3. 類加載器
Java類加載器是一部分的Java運行時環(huán)境可以動態(tài)加載Java類到Java虛擬機。由于類加載器的原因,Java運行時系統(tǒng)不需要了解文件和文件系統(tǒng)。
Java類不會一次全部加載到內(nèi)存中,而是在應(yīng)用程序需要時加載。此時,JRE將調(diào)用Java ClassLoader,并且這些ClassLoader將類動態(tài)加載到內(nèi)存中。
并非所有類都由單個ClassLoader加載。根據(jù)類的類型和類的路徑,決定加載該特定類的ClassLoader。要了解加載類的ClassLoader,請使用getClassLoader()方法。所有類均基于其名稱進行加載,如果未找到這些類中的任何一個,則它將返回NoClassDefFoundError或ClassNotFoundException。
1. Java Classloader具有以下三種類型:
1.BootStrap類加載器:Bootstrap類加載器是一種機器代碼,當(dāng)JVM調(diào)用它時會啟動操作。它不是一個Java類。它的工作是加載第一個純Java ClassLoader。Bootstrap ClassLoader從rt.jar位置加載類。Bootstrap ClassLoader沒有任何父ClassLoader。也稱為Primodial ClassLoader。
2.擴展ClassLoader:擴展ClassLoader是Bootstrap ClassLoader的子級,并從相應(yīng)的JDK擴展庫中加載核心Java類的擴展。它從jre / lib / ext目錄或系統(tǒng)屬性java.ext.dirs指向的任何其他目錄中加載文件。
3.系統(tǒng)類加載器:應(yīng)用程序類加載器也稱為系統(tǒng)類加載器。它加載在環(huán)境變量CLASSPATH,-classpath或-cp命令行選項中找到的應(yīng)用程序類型類。Application ClassLoader是Extension ClassLoader的子類。
注意:ClassLoader委托層次結(jié)構(gòu)模型始終按Application ClassLoader-> Extension ClassLoader-> Bootstrap ClassLoader的順序運行。始終給Bootstrap ClassLoader更高的優(yōu)先級,其次是Extension ClassLoader,然后是Application ClassLoader。
2 Java ClassLoader有功能性三個原則,它們是:
1.委托模型:Java虛擬機和Java ClassLoader使用一種稱為“ 委托層次算法”的算法將類加載到Java文件中。
ClassLoader基于委托模型提供的一組操作進行工作。他們是:
ClassLoader始終遵循委托層次結(jié)構(gòu)原則。
每當(dāng)JVM遇到一個類時,它都會檢查該類是否已加載。
如果該類已經(jīng)在方法區(qū)域中加載,則JVM繼續(xù)執(zhí)行。
如果該類不在方法區(qū)域中,則JVM要求Java ClassLoader子系統(tǒng)加載該特定類,然后ClassLoader子系統(tǒng)將控件移交給Application ClassLoader。
然后,應(yīng)用程序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在應(yīng)用程序類路徑中搜索該類。如果該類可用,則將其加載,否則,將生成ClassNotFoundException異常。
2.可見性原則:可見性原則指出,父ClassLoader加載的類對子ClassLoader可見,但子ClassLoader加載的類對父 ClassLoader不可見。假設(shè)擴展類加載器已加載了GEEKS.class類,則該類僅對擴展類加載器和應(yīng)用程序類加載器可見, 而對引導(dǎo)類加載器不可見。如果再次嘗試使用Bootstrap ClassLoader加載該類,它將給出異常java.lang.ClassNotFoundException。
3.Uniqueness 屬性:Uniquesness屬性可確保類是唯一的,并且不會重復(fù)類。這還確保了由父類加載器加載的類不會由子類加載器加載。如果父類加載器無法找到該類,則只有當(dāng)前實例自己會嘗試這樣做。
Java.lang.ClassLoader的方法
在JVM請求該類之后,將遵循一些步驟以加載一個類。按照委托模型加載類,但是有一些重要的方法或函數(shù)在加載類中起著至關(guān)重要的作用。
loadClass(String name,boolean resolve):此方法用于加載JVM引用的類。它以類的名稱為參數(shù)。類型為loadClass(String,boolean)。
defineClass():defineClass()方法是最終方法,不能被覆蓋。此方法用于將字節(jié)數(shù)組定義為class的實例。如果該類無效,則拋出ClassFormatError。
findClass(String name):此方法用于查找指定的類。此方法僅查找但不加載類。
findLoadedClass(String name):此方法用于驗證JVM引用的Class是否先前已加載。
Class.forName(String name,boolean initialize,ClassLoader loader):此方法用于加載類以及初始化類。此方法還提供選擇任何一個ClassLoader的選項。如果ClassLoader參數(shù)為NULL,則使用Bootstrap ClassLoader。
示例:在加載類之前執(zhí)行以下代碼:
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);
}
}
}
注意:如果已經(jīng)加載了一個類,它將返回它。否則,它將對新類的搜索委托給父類加載器。如果父類加載器找不到該類,則loadClass()調(diào)用方法findClass()來查找和加載該類。
看完上述內(nèi)容是否對您有幫助呢?如果還想對相關(guān)知識有進一步的了解或閱讀更多相關(guān)文章,請關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道,感謝您對創(chuàng)新互聯(lián)的支持。