JVM---類載入器
阿新 • • 發佈:2019-08-22
簡介
我們一直都知道java原始碼經過編譯,變為.class字尾名的位元組碼,經過類載入器載入進虛擬機器,然後進行使用。那麼我們有考慮過什麼是類載入器,類載入器從哪兒載入,什麼時候去載入,載入到哪裡。本文將逐一解答這些問題。
什麼是類載入器
類載入器指的是將類的.class檔案中的二進位制資料讀入到記憶體當中,將其放在執行時資料區的方法區內,然後在記憶體中建立一個java.lang.Class物件(規範並未說明Class物件位於哪裡,HotSPot虛擬機器將其放在了方法區內)用來封裝類在方法區內的資料結構。
JVM中類載入週期
所有的java虛擬機器實現必須在每個類或介面被java程式”首次主動使用“時才初始化他們(初始化只會執行一次)。型別的載入,連線與初始化過程都是在程式執行期間完成的,主要分為以下三個階段:
- 載入:查詢並載入類的二進位制資料
- 連線:確定類與類之間的關係
- 驗證:確保被載入類的正確性,位元組碼沒被惡意修改
- 準備:為類的靜態變數分配記憶體,並將其初始化為預設值,eg:public static int i = 1,這個階段會為整型型別初始化分配記憶體,並將預設值賦為0.
- 解析:把類中的符號引用轉換為直接引用,用指標方式直接定位。
- 初始化階段:為類的靜態變數賦予正確的初始值
類載入器都可能會在哪裡加.class檔案
- 從本地系統中直接載入
- 通過網路下載.class檔案
- 從zip,jar等歸檔檔案中載入.class檔案
- 將java原始檔動態編譯為.class檔案
- 從專有資料庫中提取.class檔案
類載入器載入類的時機
jvm在載入類的時候,是Java程式對類的使用的時候。
使用方式分為兩種:
- 主動使用(在位元組碼的層面上進行區分,大概七種)
- 建立類的例項
- 訪問某個類或介面的靜態變數,或者對該靜態變數賦值(助記符:getstatic putstatic )
- 呼叫類的靜態方法(助記符:invokestatic)
- 反射
Class.forName(“java.lang.String”)
- 初始化一個類的子類,初始化child時候,會對parent進行初始化
- java虛擬機器啟動時被標記為啟動類的類
- JDK1.7開始提供的動態語言支援:java.lang.invoke.MethodHandler例項的解析結果REF_getStatic,REF_putStatic,REF_invokeStatic控制代碼對應的類沒有初始化,則初始化。
- 被動使用
除了主動使用之外,其他使用Java類的方式都被稱為被動使用,都不會導致類的初始化
Java虛擬機器與程式的生命週期:類解除安裝
Java虛擬機器結束生命週期:
- 執行System.exit()方法
- 程式正常執行結束
- 程式在執行過程中遇到異常或錯誤而異常終止
- 由於作業系統出現錯誤而導致java虛擬機器程序終止