java虛擬機原理:類加載過程詳解
一、Java 類加載過程
1、字節(jié)碼編譯
編寫好 Java 源碼 Student.java ,
使用 javac 將上述 Java 源碼編譯成 Class 字節(jié)碼文件 Student.class ,
2、加載
加載 : 通過 " 類加載子系統(tǒng) " 將該字節(jié)碼文件 , 加載到 Java 虛擬機內(nèi)存中 的 方法區(qū) , 然后開始執(zhí)行 " 連接 " 操作 ,
類加載時機 : Java 程序執(zhí)行時 , 并不是一開始將所有的字節(jié)碼文件都加載到內(nèi)存中 , 而是用到時才進行加載 ;
- 通過 new 關(guān)鍵字創(chuàng)建實例對象 ;
- 通過 Class 反射 獲取類 ;
- 如 : Class.forName(“Xxx”) 獲取類 ;
- 序列化 / 反序列化 ;
- 調(diào)用 clone 克隆對象 ;
- 有 main 函數(shù)的類 , 會默認自動加載 ;
- 調(diào)用子類 , 如果之前沒有加載過父類 , 則 自動加載父類 ;
3、連接
連接操作 分為 3 3 3 個步驟 :
- 驗證 : 對 字節(jié)碼文件 進行校驗 , 查看該字節(jié)碼格式是否正確 , 如 : 是否以 0xCAFEBABE 開頭 , 字段表 , 方發(fā)表 , 屬性表 等格式是否正確 , 進行校驗 ;
- 校驗示例 : 假設(shè)校驗如下字節(jié)碼數(shù)據(jù) , 原始數(shù)據(jù)是 【Java 虛擬機原理】Class 字節(jié)碼二進制文件分析 一 ( 字節(jié)碼文件附加信息 | 魔數(shù) | 次版本號 | 主版本號 | 常量池個數(shù) ) 二、字節(jié)碼文件示例 章節(jié)中的 Java 源碼 , Class 字節(jié)碼 , 字節(jié)碼附加信息 ;
在 Student 構(gòu)造方法中 , 會調(diào)用到 1: invokespecial #1 父類構(gòu)造方法 , 如果父類有有參的構(gòu)造方法且沒有聲明無參構(gòu)造方法 , 子類必須實現(xiàn)一個相同參數(shù)的構(gòu)造方法 , 否則就會報錯 ;
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 }
- 準備 : 在該階段 , 在 方法區(qū) 中 , 為 類中的靜態(tài)變量 進行內(nèi)存劃分 , 并對這些靜態(tài)變量進行 默認值賦值 , 一般賦值 0 , null 等默認值 ; 即使靜態(tài)變量 static int a = 5 已經(jīng)有了賦值 , 但是在該階段暫時給該靜態(tài)變量賦值 0 ;
- 解析 : 將 " 常量池 " 中的 " 符號引用 " 轉(zhuǎn)為 " 直接引用 " ;
符號引用 : 下面就是 常量池中的 符號引用 , 引用是 以符號的形式表示出來 的 , 這并不是內(nèi)存中的引用 ; 直接引用 是 將 #1 = Methodref #4.#17 樣式的 符號引用 轉(zhuǎn)為 指向內(nèi)存地址 的 指針引用 ; JVM 線程棧 的 棧幀 中的 動態(tài)鏈接 , 就是持有的一個指向內(nèi)存的指針 , 該指針指向 棧幀 對應(yīng)方法 在運行時 常量池中的 內(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 虛擬機原理】Class 字節(jié)碼二進制文件分析 一 ( 字節(jié)碼文件附加信息 | 魔數(shù) | 次版本號 | 主版本號 | 常量池個數(shù) ) 二、字節(jié)碼文件示例 章節(jié)中的 Java 源碼 , Class 字節(jié)碼 , 字節(jié)碼附加信息 ; )
4、初始化
初始化 : 對變量進行 指定賦值 ;
如 : 有靜態(tài)變量 static int a = 5
, 在 連接 過程中的 準備 階段 , 為該變量賦值默認值 0 ; 在 初始化 階段 , 為其賦值 代碼 中設(shè)置的真正的 指定初始值 5 ;
總結(jié)
借助下圖理解類加載過程 ;
本篇文章就到這里了,希望能夠給你帶來幫助,也希望您能夠多多關(guān)注腳本之家的等多內(nèi)容!
相關(guān)文章
Java中比較運算符compareTo()、equals()與==的區(qū)別及應(yīng)用總結(jié)
這篇文章主要給大家介紹了關(guān)于Java中比較運算符compareTo()、equals()與==的區(qū)別及應(yīng)用的相關(guān)資料,文中通過示例代碼介紹的非常詳細,需要的朋友可以參考借鑒,下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2018-09-09java LRU(Least Recently Used )詳解及實例代碼
這篇文章主要介紹了java LRU(Least Recently Used )詳解及實例代碼的相關(guān)資料,Java里面實現(xiàn)LRU緩存通常有兩種選擇,一種是使用LinkedHashMap,一種是自己設(shè)計數(shù)據(jù)結(jié)構(gòu),使用鏈表+HashMap,需要的朋友可以參考下2016-11-11Spring Security使用多種加密方式進行密碼校驗的代碼示例
在Web應(yīng)用中,密碼的安全存儲和驗證是至關(guān)重要的,本文將通過一個具體的代碼示例,介紹和總結(jié)如何在Spring Security中使用多種加密方式進行密碼校驗,文中通過代碼講解得非常詳細,需要的朋友可以參考下2024-06-06Mybatis 數(shù)據(jù)庫連接池的實現(xiàn)示例
在Java應(yīng)用程序中,與數(shù)據(jù)庫的連接是非常昂貴的,因此,當(dāng)我們使用MyBatis進行數(shù)據(jù)操作時,需要一個連接池來分配并管理這些連接,本文主要介紹了Mybatis 數(shù)據(jù)庫連接池的實現(xiàn)示例,具有一定的參考價值,感興趣的可以了解一下2023-10-10SpringBoot+MinIO實現(xiàn)文件切片極速詳解
在現(xiàn)代Web應(yīng)用中,文件上傳是一個常見的需求,尤其是對于大文件的上傳,如視頻、音頻或大型文檔,所以本文就來為大家介紹一下如何使用Spring Boot和MinIO實現(xiàn)文件切片極速上傳技術(shù)吧2023-12-12