java虛擬機(jī)原理:類加載過(guò)程詳解
一、Java 類加載過(guò)程
1、字節(jié)碼編譯
編寫(xiě)好 Java 源碼 Student.java ,
使用 javac 將上述 Java 源碼編譯成 Class 字節(jié)碼文件 Student.class ,
2、加載
加載 : 通過(guò) " 類加載子系統(tǒng) " 將該字節(jié)碼文件 , 加載到 Java 虛擬機(jī)內(nèi)存中 的 方法區(qū) , 然后開(kāi)始執(zhí)行 " 連接 " 操作 ,
類加載時(shí)機(jī) : Java 程序執(zhí)行時(shí) , 并不是一開(kāi)始將所有的字節(jié)碼文件都加載到內(nèi)存中 , 而是用到時(shí)才進(jìn)行加載 ;
- 通過(guò) new 關(guān)鍵字創(chuàng)建實(shí)例對(duì)象 ;
- 通過(guò) Class 反射 獲取類 ;
- 如 : Class.forName(“Xxx”) 獲取類 ;
- 序列化 / 反序列化 ;
- 調(diào)用 clone 克隆對(duì)象 ;
- 有 main 函數(shù)的類 , 會(huì)默認(rèn)自動(dòng)加載 ;
- 調(diào)用子類 , 如果之前沒(méi)有加載過(guò)父類 , 則 自動(dòng)加載父類 ;
3、連接
連接操作 分為 3 3 3 個(gè)步驟 :
- 驗(yàn)證 : 對(duì) 字節(jié)碼文件 進(jìn)行校驗(yàn) , 查看該字節(jié)碼格式是否正確 , 如 : 是否以 0xCAFEBABE 開(kāi)頭 , 字段表 , 方發(fā)表 , 屬性表 等格式是否正確 , 進(jìn)行校驗(yàn) ;
- 校驗(yàn)示例 : 假設(shè)校驗(yàn)如下字節(jié)碼數(shù)據(jù) , 原始數(shù)據(jù)是 【Java 虛擬機(jī)原理】Class 字節(jié)碼二進(jìn)制文件分析 一 ( 字節(jié)碼文件附加信息 | 魔數(shù) | 次版本號(hào) | 主版本號(hào) | 常量池個(gè)數(shù) ) 二、字節(jié)碼文件示例 章節(jié)中的 Java 源碼 , Class 字節(jié)碼 , 字節(jié)碼附加信息 ;
在 Student 構(gòu)造方法中 , 會(huì)調(diào)用到 1: invokespecial #1 父類構(gòu)造方法 , 如果父類有有參的構(gòu)造方法且沒(méi)有聲明無(wú)參構(gòu)造方法 , 子類必須實(shí)現(xiàn)一個(gè)相同參數(shù)的構(gòu)造方法 , 否則就會(huì)報(bào)錯(cuò) ;
Constant pool:
#1 = Methodref #4.#17 // java/lang/Object."<init>":()V
{
public Student();
descriptor: ()V
flags: ACC_PUBLIC
Code:
stack=1, locals=1, args_size=1
0: aload_0
1: invokespecial #1 // Method java/lang/Object."<init>":()V
4: return
LineNumberTable:
line 1: 0
}
- 準(zhǔn)備 : 在該階段 , 在 方法區(qū) 中 , 為 類中的靜態(tài)變量 進(jìn)行內(nèi)存劃分 , 并對(duì)這些靜態(tài)變量進(jìn)行 默認(rèn)值賦值 , 一般賦值 0 , null 等默認(rèn)值 ; 即使靜態(tài)變量 static int a = 5 已經(jīng)有了賦值 , 但是在該階段暫時(shí)給該靜態(tài)變量賦值 0 ;
- 解析 : 將 " 常量池 " 中的 " 符號(hào)引用 " 轉(zhuǎn)為 " 直接引用 " ;
符號(hào)引用 : 下面就是 常量池中的 符號(hào)引用 , 引用是 以符號(hào)的形式表示出來(lái) 的 , 這并不是內(nèi)存中的引用 ; 直接引用 是 將 #1 = Methodref #4.#17 樣式的 符號(hào)引用 轉(zhuǎn)為 指向內(nèi)存地址 的 指針引用 ; JVM 線程棧 的 棧幀 中的 動(dòng)態(tài)鏈接 , 就是持有的一個(gè)指向內(nèi)存的指針 , 該指針指向 棧幀 對(duì)應(yīng)方法 在運(yùn)行時(shí) 常量池中的 內(nèi)存地址 ; 該內(nèi)存地址是在 方法區(qū) 中的 ;
Constant pool: #1 = Methodref #4.#17 // java/lang/Object."<init>":()V #2 = Fieldref #3.#18 // Student.name:Ljava/lang/String; #3 = Class #19 // Student #4 = Class #20 // java/lang/Object
( 分析的數(shù)據(jù)是 【Java 虛擬機(jī)原理】Class 字節(jié)碼二進(jìn)制文件分析 一 ( 字節(jié)碼文件附加信息 | 魔數(shù) | 次版本號(hào) | 主版本號(hào) | 常量池個(gè)數(shù) ) 二、字節(jié)碼文件示例 章節(jié)中的 Java 源碼 , Class 字節(jié)碼 , 字節(jié)碼附加信息 ; )
4、初始化
初始化 : 對(duì)變量進(jìn)行 指定賦值 ;
如 : 有靜態(tài)變量 static int a = 5 , 在 連接 過(guò)程中的 準(zhǔn)備 階段 , 為該變量賦值默認(rèn)值 0 ; 在 初始化 階段 , 為其賦值 代碼 中設(shè)置的真正的 指定初始值 5 ;
總結(jié)
借助下圖理解類加載過(guò)程 ;

本篇文章就到這里了,希望能夠給你帶來(lái)幫助,也希望您能夠多多關(guān)注腳本之家的等多內(nèi)容!
相關(guān)文章
java算法入門之有效的括號(hào)刪除有序數(shù)組中的重復(fù)項(xiàng)實(shí)現(xiàn)strStr
大家好,我是哪吒,一個(gè)熱愛(ài)編碼的Java工程師,本著"欲速則不達(dá),欲達(dá)則欲速"的學(xué)習(xí)態(tài)度,在程序猿這條不歸路上不斷成長(zhǎng),所謂成長(zhǎng),不過(guò)是用時(shí)間慢慢擦亮你的眼睛,少時(shí)看重的,年長(zhǎng)后卻視若鴻毛,少時(shí)看輕的,年長(zhǎng)后卻視若泰山,成長(zhǎng)之路,亦是漸漸放下執(zhí)念,內(nèi)心歸于平靜的旅程2021-08-08
SpringBoot項(xiàng)目中@RestControllerAdvice全局異常失效問(wèn)題的解決
@RestController注解是一個(gè)用于定義RESTful Web服務(wù)的控制器的特殊注解,它是@Controller和@ResponseBody注解的結(jié)合體,意味著你不需要在每個(gè)處理請(qǐng)求的方法上都添加@ResponseBody,本文給大家介紹了解決SpringBoot項(xiàng)目中@RestControllerAdvice全局異常失效問(wèn)題2024-11-11
Spring lazy-init 懶加載的原理小結(jié)
lazy-init 是一個(gè)非常重要的屬性,可以優(yōu)化應(yīng)用的啟動(dòng)時(shí)間,尤其是在處理大量bean或者復(fù)雜依賴關(guān)系時(shí),可以顯著提高應(yīng)用的響應(yīng)速度,本文主要介紹了Spring lazy-init 懶加載的原理小結(jié),感興趣的可以了解一下2025-04-04
java 直接調(diào)用python腳本,并傳遞參數(shù)代碼實(shí)例
這篇文章主要介紹了java調(diào)用python腳本傳遞參數(shù)的方法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-04-04
JAVA實(shí)現(xiàn)簡(jiǎn)單搶紅包算法(模擬真實(shí)搶紅包)
這篇文章主要介紹了JAVA實(shí)現(xiàn)簡(jiǎn)單搶紅包算法(模擬真實(shí)搶紅包)的實(shí)例代碼,非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友可以參考下2016-12-12
Java字符流和字節(jié)流對(duì)文件操作的區(qū)別
本篇文章主要介紹了Java的IO流分為字符流(Reader,Writer)和字節(jié)流(InputStream,OutputStream),字節(jié)流顧名思義字節(jié)流就是將文件的內(nèi)容讀取到字節(jié)數(shù)組,對(duì)初學(xué)者很有用,有需要的朋友可以了解一下。2016-10-10

