Java虛擬機(jī)JVM類(lèi)加載機(jī)制(從類(lèi)文件到虛擬機(jī))
一、類(lèi)加載機(jī)制簡(jiǎn)介
什么是類(lèi)的加載
類(lèi)的加載指的是將類(lèi)的.class文件中的二進(jìn)制數(shù)據(jù)讀入到內(nèi)存中,將其放在運(yùn)行時(shí)數(shù)據(jù)區(qū)的方法區(qū)內(nèi),然后在堆區(qū)創(chuàng)建一個(gè)java.lang.Class對(duì)象,用來(lái)封裝類(lèi)在方法區(qū)內(nèi)的數(shù)據(jù)結(jié)構(gòu)。類(lèi)的加載的最終產(chǎn)品是位于堆區(qū)中的Class對(duì)象,Class對(duì)象封裝了類(lèi)在方法區(qū)內(nèi)的數(shù)據(jù)結(jié)構(gòu),并且向Java程序員提供了訪問(wèn)方法區(qū)內(nèi)的數(shù)據(jù)結(jié)構(gòu)的接口。

類(lèi)加載機(jī)制:所謂的類(lèi)加載機(jī)制就是虛擬機(jī)將class文件加載到內(nèi)存,并對(duì)數(shù)據(jù)進(jìn)行驗(yàn)證,轉(zhuǎn)換解析和初始化,形成虛擬機(jī)可以直接使用的java類(lèi)型(即java.lang.class)
JVM的類(lèi)加載機(jī)制分為五個(gè)部分:加載,驗(yàn)證,準(zhǔn)備,解析,初始化,圖示:

二、類(lèi)加載機(jī)制過(guò)程
2.1、加載(Load)
所謂JVM加載過(guò)程,是查找和導(dǎo)入class文件,加載過(guò)程:
(1)通過(guò)類(lèi)的全限定名獲取這個(gè)類(lèi)的二進(jìn)制字節(jié)流;
(2)將字節(jié)流所代表的靜態(tài)存儲(chǔ)結(jié)構(gòu)轉(zhuǎn)換為方法區(qū)的運(yùn)行時(shí)數(shù)據(jù)結(jié)構(gòu);

(3)在JVM堆中生成代表這個(gè)類(lèi)的java.lang.class對(duì)象(作為方法區(qū)中這些數(shù)據(jù)的訪問(wèn)入口)

2.2、連接(Linking)
2.2.1、驗(yàn)證(Verify)
JVM驗(yàn)證(Verify)這個(gè)過(guò)程是為了保證被加載類(lèi)的正確性,保證其它后續(xù)步驟的正確正常執(zhí)行,驗(yàn)證的過(guò)程包括:
- 文件格式驗(yàn)證
- 元數(shù)據(jù)驗(yàn)證
- 字節(jié)碼驗(yàn)證
- 符號(hào)引用驗(yàn)證
2.2.2、準(zhǔn)備(Prepare)
準(zhǔn)備(Prepare)階段,是為類(lèi)變量分配內(nèi)存并設(shè)置初始化值的。
eg:
public static int v = 9092;
注意:在類(lèi)加載的準(zhǔn)備(Prepare)階段,v變量是賦值為0的而不是9092,這個(gè)值是在后續(xù)過(guò)程才賦值的
private static int i;
public static void main(String[] args) {
// 正常打印出0,靜態(tài)變量在類(lèi)加載的準(zhǔn)備階段會(huì)賦值0
System.out.println(i);
}
public static void main(String[] args) {
// 編譯報(bào)錯(cuò),因?yàn)榫植孔兞繘](méi)賦值不會(huì)自動(dòng)生成初始化值
int i;
System.out.println(i);
}
2.2.3、解析(Resolve)
這個(gè)階段是將常量池中的符號(hào)引用轉(zhuǎn)換為直接引用的過(guò)程。所謂符號(hào)引用就是class文件中的:
1. CONSTANT_Class_info 2. CONSTANT_Field_info 3. CONSTANT_Method_info // 等等 ...
直接引用可以是指向目標(biāo)的指針,相對(duì)偏移量或是一個(gè)能間接定位到目標(biāo)的句柄。
直接引用和字符引用一個(gè)最明顯的區(qū)別是,直接引用是目標(biāo)是已經(jīng)被加載到內(nèi)存的,而字符引用并不一定已經(jīng)加載到內(nèi)存。
2.3、初始化(Initialize)
類(lèi)加載的初始化階段,是對(duì)類(lèi)的變量和代碼塊執(zhí)行初始化操作,是執(zhí)行類(lèi)構(gòu)造器的過(guò)程,換句話(huà)說(shuō)是對(duì)類(lèi)的靜態(tài)變量,靜態(tài)代碼塊執(zhí)行初始化操作
三、類(lèi)加載器Classloader
3.1、類(lèi)加載器簡(jiǎn)介
類(lèi)的加載過(guò)程是在JVM之外的,目的是為了讓?xiě)?yīng)用程序決定如何獲取需要的類(lèi)。
類(lèi)加載,也即類(lèi)加載器通過(guò)類(lèi)的全限定名獲取其定義的二進(jìn)制字節(jié)流,顧名思義,類(lèi)加載器就是來(lái)加載class文件的。
3.2、類(lèi)加載器分類(lèi)
類(lèi)加載器可以分為啟動(dòng)類(lèi)加載器,拓展類(lèi)加載器,應(yīng)用程序類(lèi)加載器

- 1)、 Bootstrap classload(啟動(dòng)類(lèi)加載器):負(fù)責(zé)加載
$JAVA_HOME中jre/lib/rt.jar里所有的class或者--Xbootclasspath系統(tǒng)參數(shù)指定路徑下的jar包。這個(gè)實(shí)現(xiàn)是由c++實(shí)現(xiàn)的 - 2)、Extension Classload(拓展類(lèi)加載器):負(fù)責(zé)加載java平臺(tái)中拓展的一些jar,包括
$JAVA_HOME中jre/lib/ext/*.jar或者-Djava.ext.dirs指定目錄下的jar包 - 3)、Application Classload(應(yīng)用程序類(lèi)加載器):負(fù)責(zé)加載
classpath中指定的jar或者Djava.class.path指定路徑的類(lèi)和jar包 - 4)、custom classload(自定義的類(lèi)加載器):通過(guò)java.lang.ClassLoader的子類(lèi)實(shí)現(xiàn)的類(lèi),屬于程序根據(jù)需要自定義拓展的類(lèi)加載器,如tomcat、jboss都會(huì)根據(jù)j2ee規(guī)范自行實(shí)現(xiàn)ClassLoader
3.3、雙親委派
類(lèi)的加載原則:按照“雙親委派”的原則加載的,當(dāng)一個(gè)類(lèi)收到了類(lèi)加載請(qǐng)求,他首先不會(huì)嘗試自己去加載這個(gè)類(lèi),而是把這個(gè)請(qǐng)求委派給父類(lèi)去完成,每一個(gè)層次類(lèi)加載器都是如此也即class類(lèi)的加載,按照自頂向下的規(guī)則,由Bootstrap Classload到custom classload,就是由上層的加載類(lèi)來(lái)加載類(lèi)
目的:不管是哪個(gè)加載器加載這個(gè)類(lèi),最終都是委托給頂層的啟動(dòng)類(lèi)加載器進(jìn)行加載,保證了使用不同的類(lèi)加載器最終得到的都是同樣一個(gè) Object 對(duì)象。
附錄:參數(shù)資料
https://docs.oracle.com/javase/specs/jvms/se8/html/index.html
以上就是Java JVM類(lèi)加載機(jī)制(從類(lèi)文件到虛擬機(jī))的詳細(xì)內(nèi)容,更多關(guān)于JVM類(lèi)加載機(jī)制的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
springBoot項(xiàng)目中的static和templates文件夾的使用
本文主要介紹了springBoot項(xiàng)目中的static和templates文件夾的使用,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2024-07-07
解決idea反編譯失敗無(wú)法查看jar包的源碼問(wèn)題
在IntelliJ IDEA中查看jar包源碼的兩種方法:下載反編譯軟件JD-GUI或安裝JavaBytecodeDecompiler插件2024-12-12
Java中String類(lèi)常用類(lèi)型實(shí)例總結(jié)
在我們開(kāi)發(fā)中經(jīng)常會(huì)用到很多的常用的工具類(lèi),這里做一個(gè)總結(jié),下面這篇文章主要給大家介紹了關(guān)于Java中String類(lèi)常用類(lèi)型的相關(guān)資料,String類(lèi)代表字符串,需要的朋友可以參考下2021-12-12
在JAVA?Web項(xiàng)目中動(dòng)態(tài)加載DLL/SO文件的方法
在JAVA?Web項(xiàng)目中,我們經(jīng)常需要調(diào)用一些第三方庫(kù)或者實(shí)現(xiàn)一些JAVA本身不支持的功能,這時(shí),我們可能會(huì)考慮使用JNI來(lái)調(diào)用DLL或SO文件,然而,因此,本文將介紹如何在JAVA?Web項(xiàng)目中動(dòng)態(tài)加載DLL/SO文件,需要的朋友可以參考下2024-12-12
使用Java實(shí)現(xiàn)一個(gè)解析CURL腳本小工具
文章介紹了如何使用Java實(shí)現(xiàn)一個(gè)解析CURL腳本的工具,該工具可以將CURL腳本中的Header解析為KV Map結(jié)構(gòu),獲取URL路徑、請(qǐng)求類(lèi)型,解析URL參數(shù)列表和Body請(qǐng)求體,感興趣的小伙伴跟著小編一起來(lái)看看吧2025-02-02

