Java虛擬機架構?面試的時候懵了吧,作爲過來人給你們講講

本文轉載自:Java虛擬機架構?面試的時候懵了吧,作爲過來人給你們講講


JVM被分爲三個主要的子系統:類加載器子系統、運行時數據區、執行引擎

類加載器子系統

Java的動態類加載功能是由類加載器子系統處理。當它在運行時(不是編譯時)首次引用一個類時,它加載、鏈接並初始化該類文件。

加載

類由此組件加載。啓動類加載器 (BootStrap class Loader)、擴展類加載器(Extension class Loader)和應用程序類加載器(Application class Loader) 這三種類加載器幫助完成類的加載。

  • 啓動類加載器:負責從啓動類路徑中加載類,無非就是rt.jar。這個加載器會被賦予最高優先級
  • 擴展類加載器:負責加載ext 目錄(jre\lib)內的類
  • 應用程序類加載器:負責加載應用程序級別類路徑,涉及到路徑的環境變量等

上述的類加載器會遵循委託層次算法(Delegation Hierarchy Algorithm)加載類文件。

鏈接

  • 校驗:字節碼校驗器會校驗生成的字節碼是否正確,如果校驗失敗,會得到校驗錯誤
  • 準備:分配內存並初始化默認值給所有的靜態變量
  • 解析:所有符號內存引用被方法區(Method Area)的原始引用所替代

初始化

這是類加載的最後階段,這裏所有的靜態變量會被賦初始值, 並且靜態塊將被執行。

運行時數據區(Runtime Data Area)

運行時數據區域被劃分爲5個主要組件:

方法區(Method Area)

所有類級別數據將被存儲在這裏,包括靜態變量。每個JVM只有一個方法區,它是一個共享的資源。

堆區(Heap Area)

所有的對象和它們相應的實例變量以及數組將被存儲在這裏。每個JVM同樣只有一個堆區。由於方法區和堆區的內存由多個線程共享,所以存儲的數據不是線程安全的。

棧區(Stack Area)

對每個線程會單獨創建一個運行時棧。對每個函數呼叫會在棧內存生成一個棧幀(Stack Frame)。所有的局部變量將在棧內存中創建。棧區是線程安全的,因爲它不是一個共享資源。棧幀被分爲三個子實體:

  • 局部變量數組:包含多少個與方法相關的局部變量並且相應的值將被存儲在這裏
  • 操作數棧:如果需要執行任何中間操作,操作數棧作爲運行時工作區去執行指令
  • 幀數據:方法的所有符號都保存在這裏。在任意異常的情況下,catch塊的信息將會被保存在幀數據裏面

PC寄存器

每個線程都有一個單獨的PC寄存器來保存當前執行指令的地址,一旦該指令被執行,pc寄存器會被更新至下條指令的地址。

本地方法棧

本地方法棧保存本地方法信息。對每一個線程,將創建一個單獨的本地方法棧。

執行引擎

分配給運行時數據區的字節碼將由執行引擎執行。執行引擎讀取字節碼並逐段執行。

解釋器

解釋器能快速的解釋字節碼,但執行卻很慢。 解釋器的缺點就是,當一個方法被調用多次,每次都需要重新解釋。

編譯器

JIT編譯器消除了解釋器的缺點。執行引擎利用解釋器轉換字節碼,但如果是重複的代碼則使用JIT編譯器將全部字節碼編譯成本機代碼。本機代碼將直接用於重複的方法調用,這提高了系統的性能。

  • 中間代碼生成器:生成中間代碼
  • 代碼優化器:負責優化上面生成的中間代碼
  • 目標代碼生成器:負責生成機器代碼或本機代碼
  • 探測器(Profiler):一個特殊的組件,負責尋找被多次調用的方法。

垃圾回收器

收集並刪除未引用的對象。可以通過調用"System.gc()"來觸發垃圾回收,但並不保證會確實進行垃圾回收。JVM的垃圾回收只收集哪些由new關鍵字創建的對象。所以,如果不是用new創建的對象,你可以使用finalize函數來執行清理。

Java本地接口 (JNI):JNI 會與本地方法庫進行交互並提供執行引擎所需的本地庫。本地方法庫:是一個執行引擎所需的本地庫的集合。


本文轉載自:Java虛擬機架構?面試的時候懵了吧,作爲過來人給你們講講

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