1. 程式人生 > >《深入分析JavaWeb技術內幕》之 7- JVM體系結構

《深入分析JavaWeb技術內幕》之 7- JVM體系結構

 JVM體系結構

7.1.2JVM體系結構詳解

我們再看看除了指令集之外,JVM還需要那些組成部分。如圖7-2所示,JVM的結構基本上由4部分組成。

 

  • 類載入器,在JVM啟動時或者在類執行時將需要的class載入到JVM中。
  • 執行引擎,執行引擎的任務是負責執行class檔案中包含的位元組碼指令,相當於實際機器上的CPU。
  • 記憶體區,將記憶體劃分成若干個區以模擬實際機器上的儲存、記錄和排程功能模組,如實際機器上的各種功能的暫存器或者PC指標的記錄器等。

JVM記憶體結構

在Java虛擬機器規範中將Java執行時資料劃分為6種

  • PC暫存器資料

  • Java棧

  • 方法區
    方法區這個儲存區域也屬於Java堆中的一部分(永久區)

  • 本地方法棧
    本地方法棧是為了JVM執行Native方法準備的空間,由於很多Native方法都是用C語言實現的,所以它通常又叫C棧。

  • 方法區與本地方法棧

  • 方法區: 
    1.又叫靜態區,跟堆一樣,被所有的執行緒共享。方法區包含所有的class和static變數。 

    2.方法區中包含的都是在整個程式中永遠唯一的元素,如class,static變數。

  • 執行時常量池
    在使用者空間Java堆上的方法區中。

 

7.2.2JVM為何選擇基於棧的結構

指令集都會有對應的架構實現,如基於暫存器的架構實現或者基於棧的架構實現,這裡的基於暫存器或者棧都是指在一個指令中的運算元是如何存取的。

JVM執行位元組碼指令是基於棧的架構,也就是所有的運算元必須先入棧,然後根據指令中的操作碼選擇從棧頂彈出若干個元素進行計算後再將結果壓入棧中。在JVM中運算元可以可以存放在每一個棧楨中的一個本地變數集中,即在每個方法呼叫時就胡igei這個方法分配一個本地變數集,這個本地變數集在編譯時就已經確定,所以運算元入棧可以直接是常量入棧或者從本地變數集中取一個變數壓入棧中。這和一般的基於暫存器的操作有所不同,一個操作需要頻繁地入棧和出棧,如進行一個加法運算,如果連個運算元都在本地變數中,那麼一個加法操作就要有5次棧操作,分別是將兩個運算元從本地變數入棧(2次入棧操作),再將兩個操作數出棧用於加法運算(2次出棧),再將加法結果壓入棧頂(1次入棧)。如果是基於暫存器的話,一般只需要將兩個運算元存入暫存器進行加法運算後再將結果存入其中一個暫存器即可,不需要那麼多的資料移動的操作。那麼為什麼JVM還要基於棧來設計呢?

JVM為何要基於棧來設計有幾個理由。一個是JVM要設計成與平臺無關的,而平臺無關性就是要保證在沒有或者有很少的暫存器的機器上也要同樣能正確地執行Java程式碼。例如,在80X86的機器上暫存器就是沒有規律的,很難針對某一款機器設計通用的基於暫存器的指令,所以基於暫存器的架構很難做到通用。在收集作業系統方面,Google的Android平臺上的Dalvik VM就是基於特定晶片(ARM)設計的基於暫存器的架構,這樣在特定晶片上實現基於暫存器的架構可能更多考慮效能,但是也犧牲了跨平臺的移植性,當然在當前的手機上這個需求還不是最迫切的。

還有一個理由是為了指令的緊湊性,因為Java的位元組碼可能在網路上傳輸,所以class檔案的大小也是設計JVM位元組碼指令的一個重要因素,如在class檔案中位元組碼除了處理兩個表跳轉的指令外,其他都是位元組對齊的,操作碼可以只佔一個位元組大小,這都是為了儘量讓編譯後的class檔案更加緊湊。

  • 7.2.3執行引擎的架構設計

    每當建立一個新的執行緒時,JVM會為這個執行緒建立一個Java棧,同時會為這個執行緒分配一個PC暫存器,並且這個PC暫存器會指向這個執行緒的第一行可執行程式碼。每當呼叫一個新方法時會在這個棧上建立一個新的棧幀資料結構,這個棧幀會保留這個方法的一些元資訊,如在這個方法中定義的區域性變數、一些用來支援常量池的解析、正常方法返回及異常處理機制等。