欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

jvm運(yùn)行原理以及類加載器實(shí)例詳解

 更新時(shí)間:2021年05月02日 10:50:41   作者:silly8543  
這篇文章主要給大家介紹了關(guān)于jvm運(yùn)行原理以及類加載器的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧

JVM運(yùn)行原理

首先從“.java”代碼文件,編譯成“.class”字節(jié)碼文件,然后類加載器將“.class”字節(jié)碼文件中的類給加載帶JVM中,最后就是JVM執(zhí)行寫好的代碼。執(zhí)行過程如下圖

類加載器

類加載過程

加載 -> 驗(yàn)證 -> 準(zhǔn)備 -> 解析 -> 初始化 -> 使用 -> 卸載

加載

一旦JVM進(jìn)程啟動(dòng)之后,一定會(huì)先把類加載到內(nèi)存中,然后從main()方法的入口代碼開始執(zhí)行

public class HelloWorld {
    public static void main(String[] args) {
        
    }
}

加載指是將類CLass文件讀入到內(nèi)存中,并創(chuàng)建一個(gè)java.lang.Class對(duì)象

類的加載器由類加載器完成,類加載器通常由JVM提供,除此之外,可以通過繼承ClassLoader基類來(lái)創(chuàng)建自己的類加載器

通過使用不同的類加載器,可以從不同來(lái)源加載類的二進(jìn)制數(shù)據(jù)

  • 從本地文件系統(tǒng)加載class文件
  • 從JAR包加載class文件,JDBC編程時(shí)用到的數(shù)據(jù)庫(kù)驅(qū)動(dòng)類就放在JAR文件中,JVM可以從JAR文件中直接加載該class文件
  • 通過網(wǎng)絡(luò)加載class文件
  • 把一個(gè)java源文件動(dòng)態(tài)編譯,并執(zhí)行加載

準(zhǔn)備階段

驗(yàn)證

根據(jù)Java虛擬機(jī)規(guī)范,來(lái)校驗(yàn)加載進(jìn)來(lái)的“.class”文件中的內(nèi)容,是否符合指定的規(guī)范,如果“.class”文件被人篡改,里面的字節(jié)碼不符合規(guī)范,那么JVM是沒法執(zhí)行這個(gè)字節(jié)碼。所在把“.class”文件加載到內(nèi)存后,必須先驗(yàn)證一下,檢驗(yàn)他必須完全符合JVM規(guī)范,才交給JVM來(lái)運(yùn)行。其主要包括四種驗(yàn)證,文件格式驗(yàn)證,元數(shù)據(jù)驗(yàn)證,字節(jié)碼驗(yàn)證,符號(hào)引用驗(yàn)證

  • 文件格式驗(yàn)證:主要驗(yàn)證字節(jié)流是否符合Class文件格式規(guī)范,并且能被當(dāng)前的虛擬機(jī)加載處理。例如:主,次版本號(hào)是否在當(dāng)前虛擬機(jī)處理的范圍之內(nèi)。常量池中是否有不被支持的常量類型。指向常量的中的索引值是否存在不存在的常量或不符合類型的常量
  • 元數(shù)據(jù)驗(yàn)證:對(duì)字節(jié)碼描述的信息進(jìn)行語(yǔ)義的分析,分析是否符合java的語(yǔ)言語(yǔ)法的規(guī)范
  • 字節(jié)碼驗(yàn)證:最重要的驗(yàn)證環(huán)節(jié),分析數(shù)據(jù)流和控制,確定語(yǔ)義是合法的,符合邏輯的。主要的針對(duì)元數(shù)據(jù)驗(yàn)證后對(duì)方法體的驗(yàn)證。保證類方法在運(yùn)行時(shí)不會(huì)有危害出現(xiàn)
  • 符號(hào)引用驗(yàn)證:主要是針對(duì)符號(hào)引用轉(zhuǎn)換為直接引用的時(shí)候,是會(huì)延伸到第三解析階段,主要去確定訪問類型等涉及到引用的情況,主要是要保證引用一定會(huì)被訪問到,不會(huì)出現(xiàn)類等無(wú)法訪問的問題

準(zhǔn)備

給引用的類分配一定的內(nèi)存空間,然后給里面的類變量(也就是static修飾的變量)分配內(nèi)存空間,來(lái)一個(gè)默認(rèn)的初始值

解析

實(shí)際上是把將類的二進(jìn)制數(shù)據(jù)中的符號(hào)引用替換成直接引用的過程,這個(gè)部分的內(nèi)容比較復(fù)雜,設(shè)計(jì)到JVM的底層

  • 符號(hào)引用:符號(hào)引用是以一組符號(hào)來(lái)描述所引用的目標(biāo),符號(hào)可以是任何的字面形式的字面量,只要不會(huì)出現(xiàn)沖突能夠定位到就行。布局和內(nèi)存無(wú)關(guān)
  • 直接引用:是指向目標(biāo)的指針,偏移量或者能夠直接定位的句柄。該引用是和內(nèi)存中的布局有關(guān)的,并且一定加載進(jìn)來(lái)的

解析主要包括:

  • 類或接口的解析
  • 字段解析
  • 類方法解析
  • 接口方法解析

初始化

初始化是為類的靜態(tài)變量賦予正確的初始值,準(zhǔn)備階段和初始化階段看似有點(diǎn)矛盾,其實(shí)是不矛盾的,如果類中有語(yǔ)句:private static int a = 10,它的執(zhí)行過程是這樣的,首先字節(jié)碼文件被加載到內(nèi)存后,先進(jìn)行鏈接的驗(yàn)證這一步驟,驗(yàn)證通過后準(zhǔn)備階段,給a分配內(nèi)存,因?yàn)樽兞縜是static的,所以此時(shí)a等于int類型的默認(rèn)初始值0,即a=0,然后到解析(后面在說(shuō)),到初始化這一步驟時(shí),才把a(bǔ)的真正的值10賦給a,此時(shí)a=10

一個(gè)非常重要的規(guī)則,就是如果初始化一個(gè)類的時(shí)候,發(fā)現(xiàn)他的父類還沒初始化,那么必須先初始化他的父類

加載器

啟動(dòng)類/根類加載器

Bootstrap ClassLoader,他主要是負(fù)責(zé)加載我們?cè)跈C(jī)器上安裝的Java目錄下的核心類的,是用原生代碼來(lái)實(shí)現(xiàn)的,并不繼承自 java.lang.ClassLoader(負(fù)責(zé)加載$JAVA_HOME中jre/lib/rt.jar里所有的class,由C++實(shí)現(xiàn),不是ClassLoader子類)。由于引導(dǎo)類加載器涉及到虛擬機(jī)本地實(shí)現(xiàn)細(xì)節(jié),開發(fā)者無(wú)法直接獲取到啟動(dòng)類加載器的引用,所以不允許直接通過引用進(jìn)行操作

擴(kuò)展類加載器

Extension ClassLoader,負(fù)責(zé)加載JRE的擴(kuò)展目錄,lib/ext或者由java.ext.dirs系統(tǒng)屬性指定的目錄中的JAR包的類。由Java語(yǔ)言實(shí)現(xiàn),父類加載器為null

應(yīng)用程序類加載器

Application ClassLoader,被稱為應(yīng)用(也稱為系統(tǒng))類加載器,它負(fù)責(zé)在JVM啟動(dòng)時(shí)加載來(lái)自Java命令的-classpath選項(xiàng)、java.class.path系統(tǒng)屬性,或者CLASSPATH換將變量所指定的JAR包和類路徑。程序可以通過ClassLoader的靜態(tài)方法getSystemClassLoader()來(lái)獲取系統(tǒng)類加載器。如果沒有特別指定,則用戶自定義的類加載器都以此類加載器作為父加載器。由Java語(yǔ)言實(shí)現(xiàn),父類加載器為ExtClassLoader。

類加載器加載Class大致要經(jīng)過如下8個(gè)步驟:

  1. 檢測(cè)此Class是否載入過,即在緩沖區(qū)中是否有此Class,如果有直接進(jìn)入第8步,否則進(jìn)入第2步
  2. 如果沒有父類加載器,則要么Parent是根類加載器,要么本身就是根類加載器,則跳到第4步,如果父類加載器存在,則進(jìn)入第3步
  3. 請(qǐng)求使用父類加載器去載入目標(biāo)類,如果載入成功則跳至第8步,否則接著執(zhí)行第5步
  4. 請(qǐng)求使用根類加載器去載入目標(biāo)類,如果載入成功則跳至第8步,否則跳至第7步
  5. 當(dāng)前類加載器嘗試尋找Class文件,如果找到則執(zhí)行第6步,如果找不到則執(zhí)行第7步
  6. 從文件中載入Class,成功后跳至第8步
  7. 拋出ClassNotFountException異常
  8. 返回對(duì)應(yīng)的java.lang.Class對(duì)象

自定義類加載器

除了上面那幾種之外,還可以自定義類加載器,去根據(jù)你自己的需求加載你的類

類加載機(jī)制

JVM的類加載機(jī)制主要有如下3種:

  • 全盤負(fù)責(zé):所謂全盤負(fù)責(zé),就是當(dāng)一個(gè)類加載器負(fù)責(zé)加載某個(gè)Class時(shí),該Class所依賴和引用其他Class也將由該類加載器負(fù)責(zé)載入,除非顯示使用另外一個(gè)類加載器來(lái)載入
  • 雙親委派:所謂的雙親委派,則是先讓父類加載器試圖加載該Class,只有在父類加載器無(wú)法加載該類時(shí)才嘗試從自己的類路徑中加載該類。通俗的講,就是某個(gè)特定的類加載器在接到加載類的請(qǐng)求時(shí),首先將加載任務(wù)委托給父加載器,依次遞歸,如果父加載器可以完成類加載任務(wù),就成功返回;只有父加載器無(wú)法完成此加載任務(wù)時(shí),才自己去加載
  • 緩存機(jī)制。緩存機(jī)制將會(huì)保證所有加載過的Class都會(huì)被緩存,當(dāng)程序中需要使用某個(gè)Class時(shí),類加載器先從緩存區(qū)中搜尋該Class,只有當(dāng)緩存區(qū)中不存在該Class對(duì)象時(shí),系統(tǒng)才會(huì)讀取該類對(duì)應(yīng)的二進(jìn)制數(shù)據(jù),并將其轉(zhuǎn)換成Class對(duì)象,存入緩沖區(qū)中。這就是為很么修改了Class后,必須重新啟動(dòng)JVM,程序所做的修改才會(huì)生效的原因

雙親委派機(jī)制

這就是所謂的**雙親委派模型:**先找父親去加載,不行的話再由兒子來(lái)加載

  • 雙親委派機(jī)制,其工作原理的是,如果一個(gè)類加載器收到了類加載請(qǐng)求,它并不會(huì)自己先去加載,而是把這個(gè)請(qǐng)求委托給父類的加載器去執(zhí)行,如果父類加載器還存在其父類加載器,則進(jìn)一步向上委托,依次遞歸,請(qǐng)求最終將到達(dá)頂層的啟動(dòng)類加載器,如果父類加載器可以完成類加載任務(wù),就成功返回,倘若父類加載器無(wú)法完成此加載任務(wù),子加載器才會(huì)嘗試自己去加載,這就是雙親委派模式,即每個(gè)兒子都很懶,每次有活就丟給父親去干,直到父親說(shuō)這件事我也干不了時(shí),兒子自己才想辦法去完成
  • 雙親委派機(jī)制的優(yōu)勢(shì):采用雙親委派模式的是好處是Java類隨著它的類加載器一起具備了一種帶有優(yōu)先級(jí)的層次關(guān)系,通過這種層級(jí)關(guān)可以避免類的重復(fù)加載,當(dāng)父親已經(jīng)加載了該類時(shí),就沒有必要子ClassLoader再加載一次。其次是考慮到安全因素,java核心api中定義類型不會(huì)被隨意替換,假設(shè)通過網(wǎng)絡(luò)傳遞一個(gè)名為java.lang.Integer的類,通過雙親委托模式傳遞到啟動(dòng)類加載器,而啟動(dòng)類加載器在核心Java API發(fā)現(xiàn)這個(gè)名字的類,發(fā)現(xiàn)該類已被加載,并不會(huì)重新加載網(wǎng)絡(luò)傳遞的過來(lái)的java.lang.Integer,而直接返回已加載過的Integer.class,這樣便可以防止核心API庫(kù)被隨意篡改

總結(jié)

到此這篇關(guān)于jvm運(yùn)行原理以及類加載器的文章就介紹到這了,更多相關(guān)jvm運(yùn)行原理及類加載器內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Java中引用類型class的用法總結(jié)

    Java中引用類型class的用法總結(jié)

    這篇文章主要為大家詳細(xì)介紹了Java中引用類型class的用法的相關(guān)資料,文中的示例代碼講解詳細(xì),對(duì)我們學(xué)習(xí)Java有一定幫助,感興趣的可以了解一下
    2022-10-10
  • 詳解Spring?Security怎么從數(shù)據(jù)庫(kù)加載我們的用戶

    詳解Spring?Security怎么從數(shù)據(jù)庫(kù)加載我們的用戶

    這篇文章主要為大家介紹了Spring?Security怎么從數(shù)據(jù)庫(kù)加載我們的用戶示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-01-01
  • Maven deploy plugin使用方式

    Maven deploy plugin使用方式

    這篇文章主要介紹了Maven deploy plugin使用方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-11-11
  • java中對(duì)HashMap的put過程解讀

    java中對(duì)HashMap的put過程解讀

    這篇文章主要介紹了java中對(duì)HashMap的put過程解讀,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-03-03
  • Spring基礎(chǔ)之AOP的概念介紹

    Spring基礎(chǔ)之AOP的概念介紹

    AOP是Spring的關(guān)鍵特性之一,雖然Spring的IOC特性并不依賴于AOP,本文重點(diǎn)介紹AOP編程中的一些術(shù)語(yǔ),這些術(shù)語(yǔ)不僅僅局限于Spring,它適用于所有的AOP編程,感興趣的朋友一起看看吧
    2022-06-06
  • Mybatis的Cursor避免OOM異常的方法詳解

    Mybatis的Cursor避免OOM異常的方法詳解

    在Mybatis中,有一個(gè)特殊的對(duì)象Cursor,這個(gè)對(duì)象的注釋上清晰的說(shuō)明了,這個(gè)類的用途,在Mybatis中使用Cursor非常簡(jiǎn)單,只要在Mapper文件中將方法的返回值設(shè)置成Cursor<T>即可,本文給大家介紹了Mybatis的Cursor避免OOM異常的方法,需要的朋友可以參考下
    2024-06-06
  • 淺析Java中對(duì)稱與非對(duì)稱加密算法原理與使用

    淺析Java中對(duì)稱與非對(duì)稱加密算法原理與使用

    密碼學(xué)是研究編制密碼和破譯密碼的技術(shù)科學(xué)。這篇文章主要為大家介紹了Java中對(duì)稱與非對(duì)稱加密算法的原理與使用,感興趣的小伙伴可以了解一下
    2023-03-03
  • CorsFilter 過濾器解決跨域的處理

    CorsFilter 過濾器解決跨域的處理

    這篇文章主要介紹了CorsFilter 過濾器解決跨域的處理操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-06-06
  • Springboot如何切換默認(rèn)的Tomcat容器

    Springboot如何切換默認(rèn)的Tomcat容器

    這篇文章主要介紹了Springboot如何切換默認(rèn)的Tomcat容器,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-06-06
  • Java CAS機(jī)制的一些理解

    Java CAS機(jī)制的一些理解

    這篇文章主要介紹了Java CAS機(jī)制的相關(guān)資料,幫助大家更好的理解和學(xué)習(xí)使用Java,感興趣的朋友可以了解下
    2021-05-05

最新評(píng)論