文章目錄
- 1. 類加載過程
- 加載
- 驗證
- 準備
- 解析
- 初始化
- 2. 雙親委派模型
- 一個類的加載流程
- 雙親委派模型的優點
- 總結
1. 類加載過程
在整個 JVM 執行過程中, 和我們程序員關系最密切的就是類加載的過程, 所以接下來我們來看下類加載的執行流程.
對于一個類來說, 它的生命周期是這樣的:
其中前 5 步是固定的順序并且也是類加載的過程, 其中中間的 3 步我們都屬于連接, 所以對于類加載來說總共分為以下幾個步驟:
- 加載
- 驗證
- 準備
- 解析
- 初始化
類加載, 是一個非常復雜的過程, 此處我們只是簡單介紹一下類加載的大致流程. 細致解析需到 Java 官方文檔進行查閱. 下面我們來看看每個步驟的具體執行內容.
加載
“加載”(Loading)階段指的是整個“類加載”(Class Loading)過程中的一個階段,在加載 Loading 階段,Java虛擬機需要完成以下三件事情:
- 通過一個類的全限定名來獲取定義此類的二進制字節流。
- 將這個字節流所代表的靜態存儲結構轉化為方法區的運行時數據結構。
- 在內存中生成一個代表這個類的java.lang.Class對象,作為方法區這個類的各種數據的訪問入口。
通俗來說, 就是找到 .class
文件, 打開文件, 讀取文件內容, 并嘗試解析里面的格式.
驗證
驗證這一階段的目的是, 確保 .class
文件的字節流中包含的信息符合《Java虛擬機規范》的全部約束要求,保證這些信息被當作代碼運行后不會危害虛擬機自身的安全。
驗證選項:
- 文件格式驗證
- 字節碼驗證
- 符號引用驗證
- …
準備
準備階段是正式為類中定義的變量(即靜態變量,被static修飾的變量)分配內存并設置類變量初始值的階段。最終的目標是構造出完整的類對象。
比如此時有這樣一行代碼:
public static int value = 123;
它在這個階段 value 的 int 值是賦為 0,而非 123。
解析
解析階段是 Java 虛擬機將常量池內的符號引用替換為直接引用的過程,也就是初始化常量的過程。
主要是初始化類中涉及到的一些字符串常量。
初始化
初始化階段,Java 虛擬機真正開始執行類中編寫的 Java 程序代碼,將主導權移交給應用程序。初始化階段就是執行類構造器方法的過程。
也就是這個環節,開始對類對象進行更具體的初始化操作。比如初始化靜態成員,執行靜態代碼塊,加載父類等等。
2. 雙親委派模型
談到類加載機制, 不得不提的一個概念就是 “雙親委派模型”.
雙親委派模型, 可以理解為就是類加載中 JVM 如何去找 .class
文件的一個過程.
JVM 加載 .class
文件時, 會使用到 “類加載器” 模塊, JVM 中自帶了三個類加載器.
如果一個類加載器收到了類加載的請求,它首先不會自己去嘗試加載這個類,而是把這個請求委派給父類加載器去完成,每一個層次的類加載器都是如此,因此所有的加載請求最終都應該傳送到最頂層的啟動類加載器中,只有當父加載器反饋自己無 法完成這個加載請求(它的搜索范圍中沒有找到所需的類)時,子加載器才會嘗試自己去完成加載。
一個類的加載流程
- 首先, 會從 Application ClassLoader 開始. 但不會立即就搜索第三方庫的目錄, 而是先把加載任務委派給父類, 讓父類先嘗試加載.
- 到了 Extension ClassLoader, 也不會立即就搜索擴展庫的目錄, 也會把加載任務委派給父類, 也讓父類嘗試加載.
- 到了 Bootstrap ClassLoader, 也想著把任務委派出去, 可是 Bootstrap ClassLoader 已經沒有父類了, 只能自己動手搜索類了. 如果找到了這個類, 就會進行后續的加載. 如果沒找到這個類, 就會將這個任務交回給子類加載器去完成.
- 任務回到了 Extension ClassLoader, 此時收到父類交回的任務后, 就會開始搜索擴展庫的目錄, 看看有沒有匹配的
.class
文件. 如果找到了這個類, 就會進行后續的加載. 如果沒找到這個類, 就會將這個任務交回給子類加載器去完成. - 任務回到 Application ClassLoader, 此時就會開始搜索第三方庫的目錄(往往是自己開發時的項目目錄), 如果找到了這個類, 就會進行后續的加載. 如果沒找到這個類, 這時就會拋出異常.
雙親委派模型的優點
- 避免重復加載類:比如 A 類和 B 類都有一個父類 C 類,那么當 A 啟動時就會將 C 類加載起來,那么在 B 類進行加載時就不需要在重復加載 C 類了。
- 安全性:使用雙親委派模型也可以保證了 Java 的核心 API 不被篡改,如果沒有使用雙親委派模型,而是每個類加載器加載自己的話就會出現一些問題,比如我們編寫一個稱為
java.lang.Object
類的話,那么程序運行的時候,系統就會出現多個不同的 Object 類,而有些 Object 類又是用戶自己提供的因此安全性就不能得到保證了。
總結
? 本文主要講解了 JVM 中的類加載過程, 以及其中涉及到的雙親委派模型, 是我們學習 Java 過程中, 需要著重了解的.
? 想了解更多知識, 請持續關注博主, 本人會不斷更新學習記錄, 跟隨我一起不斷學習.
? 感謝你們的耐心閱讀, 博主本人也是一名學生, 也還有需要很多學習的東西. 寫這篇文章是以本人所學內容為基礎, 日后也會不斷更新自己的學習記錄, 我們一起努力進步, 變得優秀, 小小菜鳥, 也能有大大夢想, 關注我, 一起學習.
再次感謝你們的閱讀, 你們的鼓勵是我創作的最大動力!!!!!