JVM類加載過程

JVM類加載分爲5個過程:加載,驗證,準備,解析,初始化,使用,卸載,以下圖所示: java

加載過程

加載

加載是指查找字節流並據此建立類的過程。git

  • (1) 數組類沒有對應的字節流,它是由JVM根據元素類型和維度,建立的。
  • (2) 除了數組類,其餘類都是JVM藉助BootStrap ClassLoaderClassLoaderExtClassLoaderAppClassloader等類加載器來查找字節流並建立的。
  • (3) 在JVM中類的惟一性是由類的全名和類加載器肯定的,相同的class文件被不一樣的類加載器加載生成的兩個類是不一樣的。

鏈接

鏈接是指將建立好的類放入JVM並使之可以很好的執行的過程。
它可分爲驗證、準備、解析三個步驟。github

  • (1) 驗證階段是爲了保證建立的類可以知足JVM的約束條件,例如:jdk版本驗證。
  • (2) 準備階段的目的是爲建立的類的靜態字段分配內存,對靜態字段具體的初始化會在初始化階段進行。
    部分虛擬機在此階段還會構造跟其餘類層次相關的數據結構(好比用來實現虛擬方法的動態綁定的方法表),在這個階段該類沒法知道其餘類、字段及其方法的地址,所以在須要引用這些成員的時候,java編譯器會生成一個符號引用,在運行階段該引用纔可以定位到具體的地址。
  • (3) 解析階段的目的是將符號引用解析成實際引用,若是符號引用指向一個未被加載的成員,那個將觸發JVM對這個類的加載。
    JVM規範並無要求在鏈接過程當中執行解析工做,它僅僅規定若是某些字段使用了符號引用,那麼在執行這些字節碼以前須要先完成對這些富豪飲用的解析。

初始化

初始化的目的是爲標記爲常量的字段賦值,以及執行clinit方法的過程。數組

在初始化一個靜態字段的時候,咱們能夠再聲明時直接賦值,也能夠在靜態代碼塊中對其進行賦值。
若是直接賦值的字段被final所修飾,而且字段爲基本數據類型和String類型,那麼該字段會被編譯標記爲常量值,其初始化直接由JVM完成。除此以外的全部直接賦值和靜態代碼塊中賦值操做,會被java編譯器放到clinit方法中。
數據結構

何時須要對類進行初始化?

(1) 虛擬機啓動的時候,初始化用戶指定的主類。
(2) 使用new該類實例化對象的時候。
(3) 訪問靜態字段或靜態方法時,初始化靜態字段或靜態方法所在類。
(4) 子類初始化會觸發父類初始化。
(5) 若是接口定義了default方法,那麼實現該接口的類初始化會觸發該接口的初始化。
(6) 使用反射API的時候。
(7) 當使用JDK1.7的動態語言支持時,若是一個java.invoke.MethodHandle實例最後的解析結果REF_getStatic、REF_putStatic、REF_invokeStatic的方法句柄,而且這個方法句柄所對應的類沒有進行過初始化,則須要先觸發其初始化。code



參考連接:
nomico271.github.io/2017/07/07/…cdn

相關文章
相關標籤/搜索