JAVA虛擬機加載類到運行過程總結

理解Java跨平臺運行原理

java之所以可以跨平臺是因爲編譯器並沒有把源碼文件直接編譯成機器指令,而是編譯成java虛擬機可以識別和運行的字節碼文件(.java->.class)
而字節碼文件是一種無關平臺的中間編譯結果,由Java虛擬機讀取,解析和運行,正因如此java虛擬機屏蔽了不同系統的平臺差異性。

因此java虛擬機不但可以運行java,Groovy,JRuby等一大批動態語言,其原理就是編譯器將源碼文件編譯成與java相同的字節碼文件,java虛擬機就可以識別此字節碼文件,從而運行這些語言。


類的加載

編譯器是將java文件編譯成class文件
而類的加載是java虛擬機把類class文件加載到內存,並對Class文件中的數據進行校驗、轉換解析和初始化,最終形成可以被虛擬機直接使用的Java類型的過程。

而且類class的加載是運行時加載

加載階段

  1. 通過一個類的全限定名來獲取定義此類的二進制字節流。

  2. 將定義類的二進制字節流所代表的靜態存儲結構轉換爲方法區的運行時數據結構。

  3. 在Java堆中的生成一個代表該類的java.lang.Class對象,作爲方法區數據的訪問入口。

Java虛擬機的類加載是通過類加載器實現的, Java中的類加載器體系結構如下:

這裏寫圖片描述

(1).BootStrap ClassLoader:啓動類加載器,負責加載存放在%JAVA_HOME%\lib目錄中的或者通被-Xbootclasspath參數所指定的路徑中的,並且被java虛擬機識別的(僅按照文件名識別,如rt.jar,名字不符合的類庫,即使放在指定路徑中也不會被加載)類庫到虛擬機的內存中,啓動類加載器無法被java程序直接引用。
這裏寫圖片描述

(2).Extension ClassLoader:擴展類加載器,由sun.misc.Launcher$ExtClassLoader實現,負責加載%JAVA_HOME%\lib\ext目錄中的,或者被java.ext.dirs系統變量所指定的路徑中的所有類庫,開發者可以直接使用擴展類加載器。
這裏寫圖片描述

(3).Application ClassLoader:應用程序類加載器,由sun.misc.Launcher$AppClassLoader實現,負責加載用戶類路徑classpath上所指定的類庫,是類加載器ClassLoader中的getSystemClassLoader()方法的返回值,開發者可以直接使用應用程序類加載器,如果程序中沒有自定義過類加載器,該加載器就是程序中默認的類加載器。
這裏寫圖片描述

加載的是我們創建的工程目錄下的所有class,且所有引用的類庫。

注意:上述三個JDK提供的類加載器雖然是父子類加載器關係,但是沒有使用繼承,而是使用了組合關係。

從JDK1.2開始,java虛擬機規範推薦開發者使用雙親委派模式(ParentsDelegation Model)進行類加載,其加載過程如下:

(1).如果一個類加載器收到了類加載請求,它首先不會自己去嘗試加載這個類,而是把類加載請求委派給父類加載器去完成。

(2).每一層的類加載器都把類加載請求委派給父類加載器,直到所有的類加載請求都應該傳遞給頂層的啓動類加載器。

(3).如果頂層的啓動類加載器無法完成加載請求,子類加載器嘗試去加載如果連最初發起類加載請求的類加載器也無法完成加載請求時,將會拋出ClassNotFoundException,而不再調用其子類加載器去進行類加載。

雙親委派 模式的類加載機制的優點是java類它的類加載器一起具備了一種帶優先級的層次關係,越是基礎的類,越是被上層的類加載器進行加載,保證了java程序的穩定運行。


執行過程

Java虛擬機對中Class類文件的加載、連接都在運行時執行,雖然類加載和連接會佔用程序的執行時間增加性能開銷,但是卻可以爲java語言帶來高度靈活性和擴展性,java的針對接口編程和類加載器機制實現的OSGi以及熱部署等就是利用了運行時類加載和連接的特性,java的Class類在虛擬機中的生命週期如下:
這裏寫圖片描述
具體每個過程的執行內容如下篇描述:
Java類的加載順序及生命週期原理解析

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章