1. 程式人生 > >認識Java虛擬機器中的類載入子系統和執行引擎

認識Java虛擬機器中的類載入子系統和執行引擎

目錄

一. JVM整體架構

JVM(Java虛擬機器)是一套以軟體方式模擬具有完整硬體系統功能,執行在一個完全隔離環境中的完整計算機系統,是物理機的軟體實現。

1. 目前主流的JVM有以下幾類

  • Sun HotSpot VM(2010年被Oracle收購)
  • BEA JRockit VM(2008年被Oracle收購)
  • IBM J9 VM
  • Azul VM
  • Apache Harmony
  • Google Dalvik VM
  • Microsoft JVM

2. JVM由三個主要子系統組成

  1. 類載入子系統(Class Loader)
  2. 執行時資料區(Runtime Data Area)
  3. 執行引擎(Execution Engine)

二. JVM類裝載子系統

(一)類載入過程

類載入:類載入器查詢class檔案並載入到虛擬機器記憶體,並對資料進行校驗、轉換解析和初始化,最終形成可以被虛擬機器直接使用的Java型別資料的過程。

1. 載入:從硬碟查詢並通過IO讀入位元組碼檔案

2. 連結:執行驗證、準備、解析步驟

  • 驗證:校驗位元組碼檔案的正確性
  • 準備:給類的靜態變數分配記憶體空間,並賦予預設值:Integer=0、string=NULL、Boolean=false...
  • 解析:類載入器載入類所引入的其他所有類

3. 初始化:對類中靜態變數初始化為指定的值,並執行靜態程式碼塊

(二)類載入器

  • 啟動類載入器(Bootstrap ClassLoader):使用C++實現(僅限於HotSpot),是虛擬機器自身的一部分。負責JRE核心類庫${JRE_HOME}/lib目錄下的類包(如rt.jar、charsets.jar等。)載入到虛擬機器中,其無法被Java程式直接引用。

  • 擴充套件類載入器(Extention ClassLoader):由ExtClassLoader實現,負責載入JRE擴充套件目錄${JRE_HOME}/lib/ext下的所有類庫,開發者可以直接使用。

  • 應用程式類載入器(Application ClassLoader):由APPClassLoader實現。負責載入使用者類路徑classpath下所指定的類庫。

  • 使用者自定義類載入器(Custom ClassLoader):負責載入使用者自定義路徑下的類包,很少使用。

參考下方示例

(三)類載入機制

1. 全盤負責委託機制

當一個ClassLoader載入一個類時,除非顯式地使用另一個ClassLoader,否則該類所依賴和引用的類也由這個ClassLoader載入。

2. 雙親委派機制(Parents Delegation Model)

當一個ClassLoader載入目標類時,它首先將載入請求委託給父類載入器(或上級類載入器)嘗試載入,當父類載入器無法完成載入(ClassLoader在自己的搜尋範圍內找不到目標類)時,子類載入器才會嘗試自己去載入目標類。

3. 雙親委派機制的優勢

  • 沙箱安全機制:我們自定義的String.class類不會被載入,防止了核心類庫被篡改。
  • 避免類的重複載入:當父類載入器載入了目標類後,就沒必要讓子類載入器再重複載入同一個類。
  • JVM對類的載入方式是按需載入,也就是在執行期間動態載入,驗證的方式見下方示例,注意在啟動時載入引數:-verbose:class

三. JVM執行引擎

執行引擎:讀取執行時資料區的Java位元組碼並逐個執行。

(一)時編譯器(JIT編譯器)

Java程式最初是通過直譯器進行解釋執行的,當虛擬機發現某個方法或程式碼塊的執行特別頻繁,就會把這些程式碼認定為“熱點程式碼”(Hot Spot Code)。

為了提高熱點程式碼的執行效率,在執行時,虛擬機器將會把這些程式碼編譯成與本地平臺相關的機器碼,並進行各種層次的優化,完成這個任務的編譯器成為即時編譯器(Just In Time Compiler,JIT編譯器)。

(二)直譯器和編譯器

許多主流的商用虛擬機器,都同時包含直譯器和編譯器。

  1. 當程式需要快速啟動和執行時,直譯器首先發揮作用,省去編譯的時間,立即執行。
  2. 當程式執行後,隨著時間的推移,編譯器逐漸發揮作用,把越來越多的程式碼編譯成原生代碼,可以提高執行效率

如果記憶體資源限制較大(部分嵌入式系統),可以使用解釋執行節約記憶體,反之可以使用編譯執行來提升效率。同時編譯器的程式碼還能退回成直譯器的程式碼。