jvm類加載機制

Java 虛擬機將字節流轉化爲 Java 類的過程。這個過程可分爲加載、連接以及初始化

三大步驟。java

  • 加載是指查找字節流,而且據此建立類的過程。加載須要藉助類加載器,在 Java 虛擬機中,類加載

器使用了雙親委派模型,即接收到加載請求時,會先將請求轉發給父類加載器。數組

  • 連接,是指將建立成的類合併至 Java 虛擬機中,使之可以執行的過程。連接還分驗證、準備和解析

三個階段。其中,解析階段爲非必須的。spa

  • 初始化,則是爲標記爲常量值的字段賦值,以及執行 < clinit > 方法的過程。類的初始化僅會被執

行一次,這個特性被用來實現單例的延遲初始化。blog

加載

加載,是指查找字節流,而且據此建立類的過程。前面提到,對於數組類來講,它並無對應的字
節流,而是由 Java 虛擬機直接生成的。對於其餘的類來講,Java 虛擬機則須要藉助類加載器來完
成查找字節流的過程。接口

由類加載器classLoadder負責類裝載,JDK 默認提供了以下幾種ClassLoader內存

  1. Bootstrp loader

Bootstrp加載器是用C++語言寫的,它是在Java虛擬機啓動後初始化的,它主要負責加載%JAVA_HOME%/jre/lib,-Xbootclasspath參數指定的路徑以及%JAVA_HOME%/jre/classes中的類。rem

  1. ExtClassLoader

Bootstrp loader加載ExtClassLoader,而且將ExtClassLoader的父加載器設置爲Bootstrp loader.ExtClassLoader是用Java寫的,具體來講就是 sun.misc.Launcher$ExtClassLoader,ExtClassLoader主要加載%JAVA_HOME%/jre/lib/ext,此路徑下的全部classes目錄以及java.ext.dirs系統變量指定的路徑中類庫。文檔

  1. AppClassLoader

Bootstrp loader加載完ExtClassLoader後,就會加載AppClassLoader,而且將AppClassLoader的父加載器指定爲 ExtClassLoader。AppClassLoader也是用Java寫成的,它的實現類是 sun.misc.Launcher$AppClassLoader,另外咱們知道ClassLoader中有個getSystemClassLoader方法,此方法返回的正是AppclassLoader.AppClassLoader主要負責加載classpath所指定的位置的類或者是jar文檔,它也是Java程序默認的類加載器。get

java採用了委託模型機制,這個機制簡單來說,就是「類裝載器有載入類的需求時,會先請示其Parent使用其搜索路徑幫忙載入,若是Parent 找不到,那麼才由本身依照本身的搜索路徑搜索類」,或者叫雙親委派模型。編譯器

連接

連接,是指將建立成的類合併至 Java 虛擬機中,使之可以執行的過程。它可分爲驗證、準備以及解
析三個階段。

  • 驗證階段的目的,在於確保被加載類可以知足 Java 虛擬機的約束條件。
  • 準備階段的目的,則是爲被加載類的靜態字段分配內存。Java 代碼中對靜態字段的具體初始化,則

會在稍後的初始化階段中進行。

在 class 文件被加載至 Java 虛擬機以前,這個類沒法知道其餘類及其方法、字段所對應的具體地
址,甚至不知道本身方法、字段的地址。所以,每當須要引用這些成員時,Java 編譯器會生成一個
符號引用。在運行階段,這個符號引用通常都可以無歧義地定位到具體目標上。

初始化

在 Java 代碼中,若是要初始化一個靜態字段,咱們能夠在聲明時直接賦值,也能夠在靜態代碼塊中
對其賦值。

類的初始化什麼時候會被觸發呢?JVM 規範枚舉了下述多種觸發狀況:

  1. 當虛擬機啓動時,初始化用戶指定的主類;
  2. 當遇到用以新建目標類實例的 new 指令時,初始化 new 指令的目標類;
  3. 當遇到調用靜態方法的指令時,初始化該靜態方法所在的類;
  4. 當遇到訪問靜態字段的指令時,初始化該靜態字段所在的類;
  5. 子類的初始化會觸發父類的初始化;
  6. 若是一個接口定義了 default 方法,那麼直接實現或者間接實現該接口的類的初始化,會觸發

該接口的初始化;

  1. 使用反射 API 對某個類進行反射調用時,初始化這個類;
  2. 當初次調用 MethodHandle 實例時,初始化該 MethodHandle 指向的方法所在的類。
相關文章
相關標籤/搜索