從萌新的角度理解 Java 類載入機制

塗印發表於2018-09-14

類載入機制

本文主要是對java中類載入機制的入門級別文章,主要介紹類載入機制基本概念,以及類載入機制主要內容。本文按照結構組織如下:

  1. 類載入機制是什麼
  2. 類載入機制主要內容
  3. 類載入機制一般用途

一丶類載入機制是什麼?

java程式從靜態文字到動態執行的過程
    java中的類載入機制,從字面意思就不難理解。就是描述class檔案載入到jvm的主要過程,class檔案是對java類的描述,載入java類的過程就是載入class檔案的過程。     類載入機制是圍繞ClassLoader這個核心類展開的,classLoader就是類載入機制中的核心類。classLoader有如下幾個主要的方法:
classLoader的核心方法.png

  • defineClass:是將位元組碼載入到JVM記憶體中,解析成Class物件的方法。
  • findClass: 該方式解析指定路徑下的class檔案生成Class物件的方法。一般defineClass方法和findClass是組合使用的,在findClass方法中依據指定路徑,獲取位元組流,然後代用defineClass方法進行解析。
  • resolveClass:解析繼承關係上的的父類,以及所引用的類,是一個遞迴解析的過程,在物件正真被例項化的時候,該方法被呼叫。
  • loadClass:該方法是上述所有方法的一站式解決方案,也是JVM自帶類載入機制。如果呼叫loadClass方法載入類,是按照JVM預設的規則載入類,如果需要定製類載入器,則通過重寫上述的三個方法可以達到效果

二丶類載入機制的主要內容

1. 誰來負責class檔案的載入

在java程式碼中,每個定義的類都是由classloader載入進來的。JVM中的類載入器之間的關係組織結構和類的繼承關係有些相似,都是一層層的,一個類載入器有父載入器,父載入器下面有許多子載入器。JVM主要提供三層類載入器:

1.1 類載入器組織結構
  • 第一層:Bootstrap ClassLoader,這個類載入器,主要複雜載入JVM自身工作所需要的類。其他人都訪問不到這個類載入器,是一個相對獨立的類載入,其上沒有父載入器,也沒有子載入器
  • 第二層:ExtClassLoader,這類載入是應用層能夠訪問到的頂層類載入器,可以認為其沒有父載入器,只有子載入器。其主要負責加System.getProperty("java.ext.dirs")目錄下的類。 -第三層:AppClassLoader,這個類載入器就是我們最常接觸的類載入器,用來接在classpath路徑下類的載入器。其父載入器是ExtClassLoader. 特別注意,從邏輯上可以定義第四層類載入器:
  • 第四層:自定義classLoader,該層不是JVM自帶的類載入器,而是我們自定義的類載入器,在整個類載入的組織結構中,可以理解為第四層,其父載入器是AppClassLoader.
    類載入器的組織結構
    在熟悉類載入器組織結構後,我們還不能回答究竟是誰負責載入java類。在介紹完**上級委託載入機制(雙親委託載入機制)**後,就可以從眾多classLoader中找到合適的類載入器載入java類了。
1.2 上級委託載入機制

上級委託載入機制
圖中的類載入器1是類載入器2的父載入器,從上往下依次類推。

  • 向上詢問:當我們使用類載入器4載入目標物件時,並不一定是類載入器4來負責該類的載入,類載入器4在確保目標類未被載入後,會將載入請求傳遞給其父載入器classloader3。classloader3會繼續重複和classloader4相同的工作,向其父載入器傳遞載入請求,載入請求最後被傳遞給頂層載入器classloader1.。在該過程中如果某層載入器發現該類已載入了,則結束載入過程,確保不重複載入。如果頂層載入機制受理了載入請求,此次載入過程就結束了。**這個過程,
  • 向下委派 如果頂層載入機制不受理該次載入請求,其會將類載入請求按原路遣返,沿途載入器將會依次檢查是否受理該次類載入請求,最後由受理載入器載入目標類。

2.類載入過程

上級委託機制回答了是誰負責載入類的這個問題,閱讀完這一節後,就可以回答JVM載入類的一般過程了。

JVM載入類的階段

  • 第一階段:該階段的主要工作是定義去哪兒找class檔案,並且通過位元組流的形式將class檔案載入到記憶體中。
  • 第二階段:該階段細分為三個小階段
    1. 位元組碼驗證:類載入對載入的位元組碼,要做許多驗證,確保class檔案格式正確,行為正確。
    2. 類準備:在該階段準備描述類中欄位,方法以及實現介面所需要的資料結構,
    3. 解析:在這個階段類載入器會將類中引用的所有相關類都載入進去,並且這是一個遞迴的過程。
  • 第三階段:初始化class物件,在這個階段靜態變數將初始化,靜態程式碼塊也是在這個時候執行的。

三丶定製類載入器

瞭解類載入機制的基本原理後,我們可以看看類載入機制在實際開發中的一些用途

  • 在自定義路徑下查詢class類檔案,當我們需要的class檔案,不是在classpath路徑下時,就需要自己實現一個類載入器來載入指定路徑下的class檔案。
  • 對要載入的類做特殊的處理,在網路傳輸類資訊時,一般會對類的位元組碼加密。在載入到JVM之前需要對類的位元組碼解密後再按傳統方法載入,這個過程就可以通過自定義類載入器實現
  • 類載入器一個比較常見的應用就是熱部署,檢查到已經載入的class檔案已經修改的時候,重新載入這個類,以實現熱部署。

Reference

[1]深入分析javaWeb技術內幕,許令波,第二版

相關文章