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

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

加載類和接口

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

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

類或接口的二進制格式一般是上面引用的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。jvm

加載過程

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

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

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

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

由於加載涉及新數據結構的分配,因此它可能會因OutOfMemoryError而失敗。

參考引用

相關文章
相關標籤/搜索