溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點(diǎn)擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

JVM加載class文件的原理機(jī)制是什么

發(fā)布時(shí)間:2022-04-28 16:47:08 來源:億速云 閱讀:145 作者:iii 欄目:開發(fā)技術(shù)

今天小編給大家分享一下JVM加載class文件的原理機(jī)制是什么的相關(guān)知識點(diǎn),內(nèi)容詳細(xì),邏輯清晰,相信大部分人都還太了解這方面的知識,所以分享這篇文章給大家參考一下,希望大家閱讀完這篇文章后有所收獲,下面我們一起來了解一下吧。

一、JVM簡介

JVM是Java Virtual Machine(Java虛擬機(jī))的縮寫,JVM是一種用于計(jì)算設(shè)備的規(guī)范,它是一個(gè)虛構(gòu)出來的計(jì)算機(jī),是通過在實(shí)際的計(jì)算機(jī)上仿真模擬各種計(jì)算機(jī)功能來實(shí)現(xiàn)的。

Java語言的一個(gè)非常重要的特點(diǎn)就是與平臺的 無關(guān)性。而使用Java虛擬機(jī)是實(shí)現(xiàn)這一特點(diǎn)的關(guān)鍵。一般的高級語言如果要在不同的平臺上運(yùn)行,至少需要編譯成不同的目標(biāo)代碼。而引入Java語言虛擬機(jī)后,Java語言在不同平臺上運(yùn)行時(shí)不需要重新編譯。Java語言使用Java虛擬機(jī)屏蔽了與平臺相關(guān)的信息,使得Java語言編譯程序只需生成在Java虛擬機(jī)上運(yùn)行的目標(biāo)代碼(字節(jié)碼),就可以在多種平臺上不加修改的運(yùn)行。Java虛擬機(jī)在執(zhí)行字節(jié)碼時(shí),把字節(jié)碼解釋成具體平臺上的及其指令執(zhí)行。這就是Java能夠“一次編譯,到處運(yùn)行”的原因。

二、JVM的組成部分

JVM加載class文件的原理機(jī)制是什么

由圖可以看出,JVM是運(yùn)行在操作系統(tǒng)之上的,它與硬件沒有直接的交互。

JVM加載class文件的原理機(jī)制是什么

1. 類加載器 Class Loader

類加載器的作用是加載類文件到內(nèi)存,比如編寫一個(gè)HelloWorld.java程序,然后通過javac編譯生成class文件。由Class Loader將class文件加載到內(nèi)存中。但是Class Loader加載class文件有格式要求。
注意:Class Loader只管加載,只要符合文件結(jié)構(gòu)就加載,至于能不能運(yùn)行,是由Execution Engine負(fù)責(zé)。
2. 執(zhí)行引擎 Exexution Engine
執(zhí)行引擎也叫作解釋器,負(fù)責(zé)解釋命令,提交操作系統(tǒng)執(zhí)行。
3. 本地接口 Native Interface
本地接口的作用是為了融合不同的編程語言為Java所用。它的初衷是為了融合C/C++程序,Java誕生的時(shí)候是C/C++橫行的時(shí)候,要想立足,必須要有一個(gè)聰明的、睿智的調(diào)用C/C++程序,于是就在內(nèi)存中專門開辟了一塊區(qū)域處理標(biāo)記為native的代碼,它的具體做法是Native Method Stack中登記native方法,在Execution Engine執(zhí)行時(shí)加載加載native libraries。目前該方法只有在與硬件有關(guān)的應(yīng)用中才會使用,在企業(yè)級應(yīng)用中已經(jīng)比較少見,因?yàn)楝F(xiàn)在的異構(gòu)領(lǐng)域間的通信很發(fā)達(dá),比如可以使用Socket通信,也可以使用WebService等。
4. 運(yùn)行數(shù)據(jù)區(qū) Runtime data area
運(yùn)行數(shù)據(jù)區(qū)使整個(gè)JVM的重點(diǎn)。我們所寫的程序都被加載到這里,之后才開始運(yùn)行,Java生態(tài)系統(tǒng)如此的繁榮,得益于該區(qū)域的優(yōu)良自治。

三、JVM加載class文件的原理機(jī)制

1. Java中的所有類,必須被裝載到JVM中才能運(yùn)行,這個(gè)裝載工作是由JVM中的類裝載器完成的,類裝載器所做的工作實(shí)質(zhì)是把類文件從硬盤讀取到內(nèi)存中,作用就是在運(yùn)行時(shí)加載類。
Java類加載器基于三個(gè)機(jī)制:委托、可見性和單一性。
(1)委托機(jī)制是指加載一個(gè)類的請求交給父類加載器,如果這個(gè)父類加載器不能夠找到或加載這個(gè)類,那么再加載它。
(2)可見性的原理是子類的加載器可以看見所有的父類加載器加載的類,而父類加載器看不到子類加載器加載的類。
(3)單一性原理是指一個(gè)類僅被加載一次,這是由委托機(jī)制確保子類加載器不會再次加載父類加載器加載過的類。
2. Java中的類大致分為三種:
(1)系統(tǒng)類
(2)擴(kuò)展類
(3)由程序員自定義的類
3. 類裝載有兩種方式
(1)隱式裝載:
程序在運(yùn)行過程中當(dāng)碰到通過new等方式生成類或者子類對象、使用類或者子類的靜態(tài)域時(shí),隱式調(diào)用類加載器加載對應(yīng)的的類到JVM中。
(2)顯式裝載:
通過調(diào)用Class.forName()或者ClassLoader.loadClass(className)等方法,顯式加載需要的類。
4. 類加載的動態(tài)性體現(xiàn)
一個(gè)應(yīng)用程序總是由n多個(gè)類組成,Java程序啟動時(shí),并不是一次把所有的類全部加載再運(yùn)行,他總是把保證程序運(yùn)行的基礎(chǔ)類一次性加載到JVM中,其他類等到JVM用到的時(shí)候再加載,這樣是為了節(jié)省內(nèi)存的開銷,因?yàn)镴ava最早就是為嵌入式系統(tǒng)而設(shè)計(jì)的,內(nèi)存寶貴,而用到時(shí)再加載這也是Java動態(tài)性的一種體現(xiàn)。
5. Java類加載器
Java中的類加載器實(shí)質(zhì)上也是也是類,功能是把類加載入JVM中,值得注意的是JVM的類加載器有三個(gè),原因有:一方面是為了分工明確,各自負(fù)責(zé)各自的區(qū)塊,另一方面為了實(shí)現(xiàn)委托模型。
層次結(jié)構(gòu)如下:
BootStrap Loader(引導(dǎo)類加載器) ----- 負(fù)責(zé)加載系統(tǒng)類

ExtClassLoader(擴(kuò)展類加載器) ----- 負(fù)責(zé)加載擴(kuò)展類
AppClassLoade(應(yīng)用類加載器)r ----- 負(fù)責(zé)加載應(yīng)用類
6. 類加載器之間如何協(xié)調(diào)工作的
Java中有三個(gè)類加載器,碰到一個(gè)類需要加載時(shí),Java采用委托模型機(jī)制來協(xié)調(diào)和區(qū)分該由哪個(gè)類加載器完成。簡單來說就是,“類裝載器有載入類的需求時(shí),會先請示其Parent使用其搜索路徑幫忙載入”,如果Parent找不到,那么才由自己依照自己的搜索路徑搜索類。
實(shí)例一:

package ClassLoaderTest;
public class ClassLoaderTest {
    public static void main(String[] args) {
        ClassLoader c1 = ClassLoaderTest.class.getClassLoader();
        System.out.println(c1);
        ClassLoader c1Parent = c1.getParent();
        System.out.println(c1Parent);
        ClassLoader c1Root = c1Parent.getParent();
        System.out.println(c1Root);
    }
}

執(zhí)行結(jié)果:

JVM加載class文件的原理機(jī)制是什么

可以看出ClassLoaderTest是由AppClassLoader加載器加載的。AppClassLoader的Parent加載器是ExtClassLoader。但是ExtClassLoader的Parent是null,在Java中是無法獲取的。
實(shí)例二:

public class Test2 {
    public void test(){
        System.out.println(Test2.class);
        System.out.println(this.getClass());
        System.out.println(Test2.class.getClassLoader());
    }
}
public class Test1 {
    public static void main(String[] args) {
        System.out.println(Test1.class.getClassLoader());
        Test2 test2 = new Test2();
        test2.test();
    }
}

執(zhí)行結(jié)果:

JVM加載class文件的原理機(jī)制是什么

7. 預(yù)先加載和依需求加載
Java運(yùn)行環(huán)境為了優(yōu)化系統(tǒng),提高程序的執(zhí)行速度,在JRE運(yùn)行的開始會將Java運(yùn)行所需要的基本類采用預(yù)先加載(pre-loading)的方法全部加載到內(nèi)存當(dāng)中,因?yàn)檫@些單元在Java程序運(yùn)行的過程當(dāng)中要經(jīng)常使用的,主要包括JRE的rt.jar文件里面所有的.class文件。
當(dāng)java.exe虛擬機(jī)開始運(yùn)行以后,它會找到安裝在機(jī)器上的JRE環(huán)境,然后把控制權(quán)交給JRE,JRE的類加載器會自動將lib目錄下的rt.jar基礎(chǔ)類別文件庫加載進(jìn)內(nèi)存,這些文件是Java程序執(zhí)行所必需的,所以系統(tǒng)在開始就將這些文件加載,避免以后的多次IO操作,從而提高程序執(zhí)行效率。然而我們在程序中需要使用自定義的類的時(shí)候就要使用依需求加載(load-on-demand)的方式,就是在Java程序需要用到的時(shí)候再加載,以減少內(nèi)存的消耗。
8. ClassLoader中一些 重要的方法

JVM加載class文件的原理機(jī)制是什么

9.什么地方適用類加載器
最經(jīng)典的例子就是AppletClassLoader,他被用來加載Applet使用的類,而Applet大部分是在網(wǎng)上使用,而非本地的操作系統(tǒng)使用。使用不同的類加載器,你可以從不同的源地址加載同一個(gè)類,它們被視為不同的類。J2EE使用多個(gè)類加載器加載不同地方的類,例如War文件由Web-app類加載器加載,而EJB-JAR中的類由另外的類加載器加載。有些服務(wù)器也支持熱部署,這是由類加載器實(shí)現(xiàn)。你也可以使用類加載器來加載數(shù)據(jù)庫或者其他持久層的數(shù)據(jù)。
10. 類加載器的階層體系
Java類加載器的工作原理:
當(dāng)執(zhí)行Java的.class文件的時(shí)候,java.exe會幫助我們找到j(luò)RE,接著找到JRE內(nèi)部的jcm.dll,這才是真正的Java虛擬機(jī)器,最后加載動態(tài)庫,激活Java虛擬機(jī)器。虛擬機(jī)激活以后,會先做一些初始化的動作,比如說讀取系統(tǒng)參數(shù)等。一旦初始化動作完成后,就會產(chǎn)生第一個(gè)類加載器-----Bootstrap Loader,Bootstrap Loader是由C++撰寫而成,這個(gè)Bootstrap所做的初始工作中,除了一些基本的初始化動作之外,最重要的就是加載Launcher.java之中的ExtClassLoader,并設(shè)定其parent為null,代表其父加載器為BootstrapLoader。然后Bootstrap loader再要求加載Launcher.java之中的AppClassLoader,并設(shè)定其parent為之前產(chǎn)生的ExtClassLoader實(shí)體。這兩個(gè)類加載器都是以靜態(tài)類的形式存在的。注意:Launcher E x t C l a s s L o a d e r . c l a s s 與 L a u n c h e r ExtClassLoader.class與Launcher ExtClassLoader.class與LauncherAppClassLoader.class都是由Bootstrap Loader所加載,所以Parent和由哪個(gè)類加載器加載沒有關(guān)系。
三者之間的關(guān)系:
Bootstrap Loader <&mdash;(extends)-----ExtClassLoader <&mdash;(extends)&mdash;AppClassLoader
這三個(gè)類加載器構(gòu)成了Java的類加載體系。它們分別從以下的路徑尋找程序所需要的類:
Bootstrap Loader:sun.boot.class.path
ExtClassLoader:java.ext.dirs
AppClassLoader:java.class.path
這三個(gè)參數(shù)可以通過System.getProperty()函數(shù)得到具體對應(yīng)的路徑。

以上就是“JVM加載class文件的原理機(jī)制是什么”這篇文章的所有內(nèi)容,感謝各位的閱讀!相信大家閱讀完這篇文章都有很大的收獲,小編每天都會為大家更新不同的知識,如果還想學(xué)習(xí)更多的知識,請關(guān)注億速云行業(yè)資訊頻道。

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI