Java虛擬機JVM類加載機制(從類文件到虛擬機)
一、類加載機制簡介
什么是類的加載
類的加載指的是將類的.class文件中的二進制數(shù)據(jù)讀入到內(nèi)存中,將其放在運行時數(shù)據(jù)區(qū)的方法區(qū)內(nèi),然后在堆區(qū)創(chuàng)建一個java.lang.Class對象,用來封裝類在方法區(qū)內(nèi)的數(shù)據(jù)結(jié)構(gòu)。類的加載的最終產(chǎn)品是位于堆區(qū)中的Class對象,Class對象封裝了類在方法區(qū)內(nèi)的數(shù)據(jù)結(jié)構(gòu),并且向Java程序員提供了訪問方法區(qū)內(nèi)的數(shù)據(jù)結(jié)構(gòu)的接口。
類加載機制:所謂的類加載機制就是虛擬機將class文件加載到內(nèi)存,并對數(shù)據(jù)進行驗證,轉(zhuǎn)換解析和初始化,形成虛擬機可以直接使用的java類型(即java.lang.class)
JVM的類加載機制分為五個部分:加載,驗證,準(zhǔn)備,解析,初始化,圖示:
二、類加載機制過程
2.1、加載(Load)
所謂JVM加載過程,是查找和導(dǎo)入class文件,加載過程:
(1)通過類的全限定名獲取這個類的二進制字節(jié)流;
(2)將字節(jié)流所代表的靜態(tài)存儲結(jié)構(gòu)轉(zhuǎn)換為方法區(qū)的運行時數(shù)據(jù)結(jié)構(gòu);
(3)在JVM堆中生成代表這個類的java.lang.class對象(作為方法區(qū)中這些數(shù)據(jù)的訪問入口)
2.2、連接(Linking)
2.2.1、驗證(Verify)
JVM驗證(Verify)這個過程是為了保證被加載類的正確性,保證其它后續(xù)步驟的正確正常執(zhí)行,驗證的過程包括:
- 文件格式驗證
- 元數(shù)據(jù)驗證
- 字節(jié)碼驗證
- 符號引用驗證
2.2.2、準(zhǔn)備(Prepare)
準(zhǔn)備(Prepare)階段,是為類變量分配內(nèi)存并設(shè)置初始化值的。
eg:
public static int v = 9092;
注意:在類加載的準(zhǔn)備(Prepare)階段,v變量是賦值為0的而不是9092,這個值是在后續(xù)過程才賦值的
private static int i; public static void main(String[] args) { // 正常打印出0,靜態(tài)變量在類加載的準(zhǔn)備階段會賦值0 System.out.println(i); }
public static void main(String[] args) { // 編譯報錯,因為局部變量沒賦值不會自動生成初始化值 int i; System.out.println(i); }
2.2.3、解析(Resolve)
這個階段是將常量池中的符號引用轉(zhuǎn)換為直接引用的過程。所謂符號引用就是class文件中的:
1. CONSTANT_Class_info 2. CONSTANT_Field_info 3. CONSTANT_Method_info // 等等 ...
直接引用可以是指向目標(biāo)的指針,相對偏移量或是一個能間接定位到目標(biāo)的句柄。
直接引用和字符引用一個最明顯的區(qū)別是,直接引用是目標(biāo)是已經(jīng)被加載到內(nèi)存的,而字符引用并不一定已經(jīng)加載到內(nèi)存。
2.3、初始化(Initialize)
類加載的初始化階段,是對類的變量和代碼塊執(zhí)行初始化操作,是執(zhí)行類構(gòu)造器的過程,換句話說是對類的靜態(tài)變量,靜態(tài)代碼塊執(zhí)行初始化操作
三、類加載器Classloader
3.1、類加載器簡介
類的加載過程是在JVM之外的,目的是為了讓應(yīng)用程序決定如何獲取需要的類。
類加載,也即類加載器通過類的全限定名獲取其定義的二進制字節(jié)流,顧名思義,類加載器就是來加載class文件的。
3.2、類加載器分類
類加載器可以分為啟動類加載器,拓展類加載器,應(yīng)用程序類加載器
- 1)、 Bootstrap classload(啟動類加載器):負(fù)責(zé)加載
$JAVA_HOME
中jre/lib/rt.jar
里所有的class或者--Xbootclasspath
系統(tǒng)參數(shù)指定路徑下的jar包。這個實現(xiàn)是由c++實現(xiàn)的 - 2)、Extension Classload(拓展類加載器):負(fù)責(zé)加載java平臺中拓展的一些jar,包括
$JAVA_HOME
中jre/lib/ext/*.jar
或者-Djava.ext.dirs
指定目錄下的jar包 - 3)、Application Classload(應(yīng)用程序類加載器):負(fù)責(zé)加載
classpath
中指定的jar或者Djava.class.path
指定路徑的類和jar包 - 4)、custom classload(自定義的類加載器):通過java.lang.ClassLoader的子類實現(xiàn)的類,屬于程序根據(jù)需要自定義拓展的類加載器,如tomcat、jboss都會根據(jù)j2ee規(guī)范自行實現(xiàn)ClassLoader
3.3、雙親委派
類的加載原則:按照“雙親委派”的原則加載的,當(dāng)一個類收到了類加載請求,他首先不會嘗試自己去加載這個類,而是把這個請求委派給父類去完成,每一個層次類加載器都是如此也即class類的加載,按照自頂向下的規(guī)則,由Bootstrap Classload到custom classload,就是由上層的加載類來加載類
目的:不管是哪個加載器加載這個類,最終都是委托給頂層的啟動類加載器進行加載,保證了使用不同的類加載器最終得到的都是同樣一個 Object 對象。
附錄:參數(shù)資料
https://docs.oracle.com/javase/specs/jvms/se8/html/index.html
以上就是Java JVM類加載機制(從類文件到虛擬機)的詳細(xì)內(nèi)容,更多關(guān)于JVM類加載機制的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
windows系統(tǒng)配置Java開發(fā)環(huán)境變量
這篇文章主要介紹了windows系統(tǒng)配置Java開發(fā)環(huán)境變量,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2021-12-12SpringBoot中的static靜態(tài)資源訪問、參數(shù)配置、代碼自定義訪問規(guī)則詳解
這篇文章主要介紹了SpringBoot的static靜態(tài)資源訪問、參數(shù)配置、代碼自定義訪問規(guī)則,本文通過示例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2023-07-07SpringBoot使用Sa-Token實現(xiàn)賬號封禁、分類封禁、階梯封禁的示例代碼
本文主要介紹了SpringBoot使用Sa-Token實現(xiàn)賬號封禁、分類封禁、階梯封禁的示例代碼,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2023-07-07淺析Java ClassName.this中類名.this關(guān)鍵字的理解
Java ClassName.this中類名.this關(guān)鍵字 的理解大家都了解多少,有不太了解的朋友可以參考下本文一起學(xué)習(xí)學(xué)習(xí)2016-05-05SpringBoot基于Mybatis攔截器和JSqlParser實現(xiàn)數(shù)據(jù)隔離
本文將介紹如何在 Spring Boot 項目中利用Mybatis的強大攔截器機制結(jié)合JSqlParser,一個功能豐富的 SQL 解析器,來輕松實現(xiàn)數(shù)據(jù)隔離的目標(biāo),本文根據(jù)示例展示如何根據(jù)當(dāng)前的運行環(huán)境來實現(xiàn)數(shù)據(jù)隔離,需要的朋友可以參考下2024-04-04在MyBatisPlus中使用@TableField完成字段自動填充的操作
這篇文章主要介紹了在MyBatisPlus中使用@TableField完成字段自動填充的操作,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2021-02-02