国产成人精品18p,天天干成人网,无码专区狠狠躁天天躁,美女脱精光隐私扒开免费观看

jvm運行原理以及類(lèi)加載器實(shí)例詳解

發(fā)布時(shí)間:2021-07-17 21:51 來(lái)源:腳本之家 閱讀:0 作者:silly8543 欄目: 編程語(yǔ)言 歡迎投稿:712375056

JVM運行原理

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

類(lèi)加載器

類(lèi)加載過(guò)程

加載 -> 驗證 -> 準備 -> 解析 -> 初始化 -> 使用 -> 卸載

加載

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

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

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

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

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

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

準備階段

驗證

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

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

準備

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

解析

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

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

解析主要包括:

  • 類(lèi)或接口的解析
  • 字段解析
  • 類(lèi)方法解析
  • 接口方法解析

初始化

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

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

加載器

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

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

擴展類(lèi)加載器

Extension ClassLoader,負責加載JRE的擴展目錄,lib/ext或者由java.ext.dirs系統屬性指定的目錄中的JAR包的類(lèi)。由Java語(yǔ)言實(shí)現,父類(lèi)加載器為null

應用程序類(lèi)加載器

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

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

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

自定義類(lèi)加載器

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

類(lèi)加載機制

JVM的類(lèi)加載機制主要有如下3種:

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

雙親委派機制

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

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

總結

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

免責聲明:本站發(fā)布的內容(圖片、視頻和文字)以原創(chuàng )、來(lái)自本網(wǎng)站內容采集于網(wǎng)絡(luò )互聯(lián)網(wǎng)轉載等其它媒體和分享為主,內容觀(guān)點(diǎn)不代表本網(wǎng)站立場(chǎng),如侵犯了原作者的版權,請告知一經(jīng)查實(shí),將立刻刪除涉嫌侵權內容,聯(lián)系我們QQ:712375056,同時(shí)歡迎投稿傳遞力量。

樱花草在线社区WWW| 大桥久未无码吹潮在线观看| 日本丰满少妇XXXX| 国产开嫩苞视频在线观看| 亚洲国产A∨无码中文777| 亚洲一区二区三区在线网址|