JVM(Java SE 11版本)加載類和接口 原 薦

本文介紹了Java虛擬機(Java SE 11版本)加載類和接口。

加載類和接口

加載是指查找具有特定名稱的類或接口類型的二進制形式的過程。典型的做法是,查找事先由Java編譯器從源代碼計算而來二進制表示,但也可能是通過動態計算。 二進制形式最終會構造成一個Class對象。

加載的精確語義在Java Java Machine Specification,Java SE 11 Edition的第5章中給出。在這裏,我們從Java編程語言的角度概述了該過程。

類或接口的二進制格式通常是上面引用的Java虛擬機規範Java SE 11版中描述的類文件格式,但只要滿足第13.1節中規定的要求,其他格式也是可能的。

類ClassLoader的方法defineClass可用於從類文件格式的二進制表示構造Class對象。

表現良好的類加載器維護這些性質:

  • 給定相同的名稱,一個好的類加載器應該總是返回相同的類對象。
  • 如果類加載器L1將類C的加載委託給另一個加載器L2,那麼對於作爲直接超類或C的直接超接口出現的任何類型T,或作爲C中的字段類型,或作爲類型方法的正式參數或 C中的構造函數,或者作爲C,L1和L2中方法的返回類型應該返回相同的Class對象。

惡意類加載器可能違反這些性質。但是,它不能破壞類型系統的安全性,因爲Java虛擬機可以防範這種情況。

有關這些問題的進一步討論,請參閱Java虛擬機規範,Java SE 11版和Java虛擬機中的動態類加載,作者:Sheng Liang和Gilad Bracha,作爲ACO SIGPLAN發佈的OOPSLA '98會議錄。通告,第33卷,第10期,1998年10月,第36-44頁。Java編程語言設計的基本原則是運行時類型系統不能被用Java編程語言編寫的代碼破壞,即使是這樣的實現也是如此。否則敏感的系統類如ClassLoader和SecurityManager。

加載過程

加載過程由類ClassLoader及其子類實現。

ClassLoader的不同子類可以實現不同的加載策略。特別地,類加載器可以緩存類和接口的二進制表示,基於預期的使用來預取它們,或者將一組相關的類加載在一起。 例如,如果找不到新編譯的類,因爲舊版本由類加載器緩存,這些活動可能對正在運行的應用程序不完全透明。但是,類加載器的責任是僅在程序中可能出現的情況下反映加載錯誤,而無需預取或組加載。

如果在類加載期間發生錯誤,那麼將在程序中(直接或間接)使用該類型的任何點拋出類LinkichError的以下子類之一的實例:

  • ClassCircularityError:無法加載類或接口,因爲它將是自己的超類或超接口(第8.1.4節,第9.1.3節,第13.4.4節)。
  • ClassFormatError:聲稱指定所請求的編譯類或接口的二進制數據格式錯誤。
  • NoClassDefFoundError:相關類加載器無法找到所請求的類或接口的定義。

因爲加載涉及新數據結構的分配,所以它可能會因OutOfMemoryError而失敗。

參考引用

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