1. 程式人生 > >Java虛擬機器:執行時資料區域-《深入理解Java虛擬機器》筆記

Java虛擬機器:執行時資料區域-《深入理解Java虛擬機器》筆記

以下內容為周志明《深入理解Java虛擬機器》中的內容摘要。寫本文來作為學習筆記。

Java 虛擬機器在執行時會將管理的記憶體劃分成若干個區域,這些區域各有各的用途,以及各自的建立和銷燬的時間。

有些隨著虛擬機器程序的啟動而存在,有些依賴使用者執行緒的啟動和結束而建立和銷燬。

Java虛擬機器所管理的執行時資料區域如下圖。 圖片來自 《深入理解Java虛擬機器》

執行時資料區分為 執行緒共享的 與 執行緒私有的 執行緒共享的區域包括:方法區,堆。 執行緒私有的區域包括:虛擬機器棧,本地方法棧,程式計數器。

這些區域都需要在執行時分配空間,除了程式計數器,當其他區域因為記憶體不足無法分配空間時,會丟擲OutOfMemory異常。

  1. 程式計數器: 執行緒私有,可以看做當前執行緒所執行位元組碼的行號指示器。每一個執行緒都有一個獨立的程式計數器。 分支,迴圈,跳轉,異常處理,執行緒恢復等功能都依賴它完成。 如果執行緒執行的是Java方法, 則記錄的是正在執行的虛擬機器位元組碼指令地址,如果執行緒執行的Native方法, 則計數器值為空。

  2. 虛擬機器棧: 生命週期與執行緒相同,每個方法執行時會建立一個棧幀(執行時的一種資料結構),每個棧幀中存放了方法 的區域性變量表,運算元棧,動態連結,方法出口等資訊。 每一個方法呼叫到執行完畢,都對應著一個棧幀在虛擬機器棧中入棧到出棧的過程。

    如果執行緒請求的棧深度虛擬機器所允許的深度,將丟擲StackOverflowError,如果虛擬機器棧可以動態擴充套件,
    擴充套件時無法申請足夠的記憶體,將丟擲OutOfMemoryError.
    
  3. 本地方法棧: 與虛擬機器棧作用類似,不過是為Native方法服務的。同樣會出現StackOverflowError以及OutOfMemoryError

  4. Java堆: 唯一目的就是存放物件例項。虛擬機器規範規定所有 物件 和 陣列 都在堆上分配,不過後來的技術發展讓這個 規定不那麼絕對了。 這塊區域是垃圾收集器管理的主要區域。也被稱為GC堆。如果收集器採取分代收集演算法,堆可以細分為Eden 空間,From Survivor空間,To Survivor空間。

  5. 方法區: 用於儲存已載入的類資訊,常量,靜態變數,即時編譯後的程式碼等資訊。可以這樣理解,是儲存Class 相關的資訊的。 根據Java虛擬機器規範,它是堆的一個邏輯部分,但有一個別名叫做Non-Heap 非堆。 當方法區無法滿足記憶體分配時,會丟擲OutOfMemoryError。

  6. 執行時常量池: 是方法區的一部分,用於存放編譯期生成的各種字面量符號引用。將在類載入後儲存進執行時常量 池。執行時常量池在執行期也可能將新的常量放入池中:例如String的intern()方法。

  7. 直接記憶體: 不是虛擬機器執行時資料區的一部分,也不是Java虛擬機器規範中定義的記憶體區域。但這部分記憶體頻繁使用,也 可能導致OutOfMemoryError。 NIO下的類通過基於通道(Channel)與緩衝區(Buffer)的I/O方式,可以直接使用本地方法分配堆外記憶體。