《深入理解Java虛擬機》第二版 第七章筆記

虛擬機類加載機制

7.2 類加載時機

類從被加載到虛擬機內存到卸載出內存,他的生命週期包括:

  • 加載(Loading)
  • 驗證(Verification)
  • 準備(Preparation)
  • 解析(Resolution)
  • 初始化(Initialization)
  • 使用(Using)
  • 卸載(Unloading)

從上到下七個階段。

需要注意:其中解析階段可以在某些情況下在初始化階段之後再開始,這是爲了支持Java語言的運行時綁定(也稱動態綁定和晚期綁定)

7.2.1 5種情況下必須對類進行初始化

  • 遇到new,getstatic,putstatic,invokestatic這4條字節碼指令時,如果類未進行過初始化,則需要先觸發其初始化。

這些字節碼指令一般使用new關鍵字實例化對象的時候,讀取或設置一個類的靜態字段(被final修飾,已在編譯器把結果放入常量池的靜態字段除外)的時候,已經調用一個類的靜態方法。

  • 使用java.lang.reflect包的方法對類進行反射調用的時候,如果類沒有進行過初始化。則先觸發初始化。
  • 如果初始化一個類,他的父類還未初始化的時候,先觸發父類的初始化。
  • 當虛擬機啓動時,用戶需要指定一個要執行的主類(main方法那個類),虛擬機先初始化這個主類。
  • 當使用JDK1.7的動態語言支持,如果一個java.lang.invoke.MethodHandle實例最後的解析結果REF_getStatic,REF_putStatic,REF_invokeStatic的方法句柄,並且這個方法的句柄所對應的類沒有進行過初始化。則先觸發其初始化。(這一種情況博主不太看懂,有會的朋友希望留言解惑。謝謝)

除此之外,所有引用類的方式都不會觸發初始化,稱爲被動引用。

  • 通過子類調用父類中定義的靜態字段,只會觸發父類的初始化,而不會觸發子類的初始化。
  • 通過數組定義來引用類,不會觸發此類的初始化。
  • 調用一個類常量的時候,不會觸發一個類的初始化。(在編譯階段常量就被存儲到NotInitialization類的常量池中,以後對調用的類的常量實際上就是調用Not這個類的常量池的引用)
  • 在一個接口被初始化的時候,並不要求其父接口都完成了初始化,只有真正使用到父接口時,纔會初始化。

7.3 類的加載過程

7.3.1 加載

(類加載過程的一個階段)

虛擬機需要做3件事:

  • 通過一個類的全限定名來獲取此類的二進制字節流
  • 將這個字節流所代表的靜態存儲結構轉化爲方法區的運行時數據結構
  • 內存中生成一個代表這個類的java.lang.Class對象,作爲方法區這個類的各種數據的訪問入口

在第一件事中,虛擬機沒有做過多規範。從哪裏獲取二進制字節流。開發人員開發了很多種選擇:

  • 從ZIP中獲取,日後成爲JAR,EAR,WAR格式的基礎。
  • 從網絡獲取,比如Applet。
  • 運行時計算生成,比如動態代理技術,在java.lang.reflect.Proxy中,就是用ProxyGenerator.generateProxyClass類來爲特定接口生成形式爲“*$Proxy”的代理類的二進制字節流。
  • 其他文件生成。比如JSP的應用,由JSP生成對應的Class類。
  • 從數據庫獲取。

補充:加載階段開發人員控性最強,可以通過系統自己的引導類加載器來完成,也能增加通過重寫類加載器的loadClass()方法自定義類加載器來完成加載。

對於數組類來說,它不通過類加載器創建,由Java虛擬機直接創建,但數組中的元素類型(Element Type)還是需要類加載器去創建。

數組類創建遵循以下規則:

  • 如果數組的元素類型是組件類型(Component Type),就遞歸地去加載這個組件類型。
  • 如果數組的組件類型不是引用類型(例如 int[] 一些基本數據的數組),數組會被標記與類加載器關聯。
  • 如果數組類的可見性與它的組件類型一致,如果組件類型不是引用類型,那數組類的可見性將默認爲public。(這句不太懂)

加載完成後,二進制字節流按照虛擬機所需的格式存儲在方法區之中

然後在內存中實例一個java.lang.Class對象,雖然它爲對象,但是它在方法區中。

此對象作爲程序訪問方法區中的這些類型數據的外部接口。

加載階段與連接階段的部分內容(如部分字節碼文件格式驗證動作)是交叉運行的。

7.3.2 驗證

目的:確保Class文件的字節流包含的信息符合虛擬機的要求,不會危害虛擬機自身的安全。

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章