1. 程式人生 > >JVM---類載入器

JVM---類載入器

簡介

我們一直都知道java原始碼經過編譯,變為.class字尾名的位元組碼,經過類載入器載入進虛擬機器,然後進行使用。那麼我們有考慮過什麼是類載入器,類載入器從哪兒載入,什麼時候去載入,載入到哪裡。本文將逐一解答這些問題。

什麼是類載入器

類載入器指的是將類的.class檔案中的二進位制資料讀入到記憶體當中,將其放在執行時資料區的方法區內,然後在記憶體中建立一個java.lang.Class物件(規範並未說明Class物件位於哪裡,HotSPot虛擬機器將其放在了方法區內)用來封裝類在方法區內的資料結構。

JVM中類載入週期

所有的java虛擬機器實現必須在每個類或介面被java程式”首次主動使用“時才初始化他們(初始化只會執行一次)。型別的載入,連線與初始化過程都是在程式執行期間完成的,主要分為以下三個階段:

  • 載入:查詢並載入類的二進位制資料
  • 連線:確定類與類之間的關係
    1. 驗證:確保被載入類的正確性,位元組碼沒被惡意修改
    2. 準備:為類的靜態變數分配記憶體,並將其初始化為預設值,eg:public static int i = 1,這個階段會為整型型別初始化分配記憶體,並將預設值賦為0.
    3. 解析:把類中的符號引用轉換為直接引用,用指標方式直接定位。
  • 初始化階段:為類的靜態變數賦予正確的初始值

類載入器都可能會在哪裡加.class檔案

  • 從本地系統中直接載入
  • 通過網路下載.class檔案
  • 從zip,jar等歸檔檔案中載入.class檔案
  • 將java原始檔動態編譯為.class檔案
  • 從專有資料庫中提取.class檔案

類載入器載入類的時機

jvm在載入類的時候,是Java程式對類的使用的時候。
使用方式分為兩種:

  • 主動使用(在位元組碼的層面上進行區分,大概七種)
    1. 建立類的例項
    2. 訪問某個類或介面的靜態變數,或者對該靜態變數賦值(助記符:getstatic putstatic )
    3. 呼叫類的靜態方法(助記符:invokestatic)
    4. 反射
    Class.forName(“java.lang.String”)
    1. 初始化一個類的子類,初始化child時候,會對parent進行初始化
    2. java虛擬機器啟動時被標記為啟動類的類
    3. JDK1.7開始提供的動態語言支援:java.lang.invoke.MethodHandler例項的解析結果REF_getStatic,REF_putStatic,REF_invokeStatic控制代碼對應的類沒有初始化,則初始化。
  • 被動使用
    除了主動使用之外,其他使用Java類的方式都被稱為被動使用,都不會導致類的初始化

Java虛擬機器與程式的生命週期:類解除安裝

Java虛擬機器結束生命週期:

  1. 執行System.exit()方法
  2. 程式正常執行結束
  3. 程式在執行過程中遇到異常或錯誤而異常終止
  4. 由於作業系統出現錯誤而導致java虛擬機器程序終止