JVM—類載入器
- 2019 年 10 月 3 日
- 筆記
簡介
我們一直都知道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虛擬機進程終止