1. 程式人生 > >讀書筆記《深入理解Java虛擬機器》 (一)JAVA記憶體區域

讀書筆記《深入理解Java虛擬機器》 (一)JAVA記憶體區域

 

.結構圖來自原書

執行緒私有區域

  • 程式計數器
  • 虛擬機器棧
  • 本地方法棧

所有執行緒共享

  • 方法區

 

程式計數器(執行緒私有)

  • 是一塊較小的記憶體空間,可以看做是當前執行緒所執行的位元組碼的行號指示器。
  • 由於JAVA虛擬機器的多執行緒是通過執行緒輪流切換並分配處理器執行時間的方式來實現的,

任何一個確定的時刻,一個處理器只會執行一條執行緒指令。

 

JAVA虛擬機器棧(執行緒私有)

  • 描述的是Java方法執行的記憶體模型,每個方法在執行的同時都會建立一個棧幀用於儲存變量表、運算元棧、動態連結、方法出口等資訊。
  • 每個方法從呼叫至完成的過程,就對應著一個棧幀在虛擬機器棧從入棧到出棧的過程。
  • 區域性變量表存放了編譯期可知的各種基本資料型別(boolean、byte、char、short、int、float、long、double)、物件引用、returnAddress型別(指向了一條位元組碼指令的地址)。
  • long、double型別的資料會佔用2個區域性變數空間。
  • 在方法執行期間不會改變區域性變量表的大小
  • 執行緒請求的棧深度大於虛擬機器允許的深度,會丟擲StackOverflowError異常, 譬如無限遞迴。
  • 虛擬機器棧如果支援動態擴充套件記憶體,而申請不到足夠的記憶體,會丟擲OutOfMeoryError異常。

本地方法棧(執行緒私有)

  • 描述的是Native方法, 功能與異常與Java虛擬機器棧基本一致。

Java堆(執行緒共享)

  • 佔用記憶體最大的一塊。
  • 幾乎只存放物件例項。
  • 是垃圾收集器管理的主要區域(從GC堆的角度看,由於現在收集器基本都採用分帶收集演算法,所以Java堆還分為新生代和老年代,在後面的章節再做了解了)。
  • 可以處於物理上不連續的記憶體空間中,只要邏輯上連續的即可。
  • 當記憶體不夠分配,會丟擲OutOfMeoryError異常。

方法區(執行緒共享)

  • 儲存已被虛擬機器載入的類資訊、常量、靜態變數、即時編譯期變異後的程式碼等資料。
  • 執行時常量池,存放編譯期生成的各種字面量和符號引用,在類載入的時候存入。
  • 當記憶體不夠分配,會丟擲OutOfMeoryError異常。

 

另1(針對遺留問題4、5)20181206:

  • 例項變數隨例項存放在堆中。
  • 靜態變數存放在方法區。
  • 常量(static final)存放在方法區中的常量池。
  • 臨時變數存放在棧。

遺留問題 20181204:

  1. Java虛擬機器棧的區域性變量表,在方法編譯期間確定所分配的空間,那執行期間產生的基本資料型別存哪了?
  2. 本地方法(Native)的使用方法、場景?
  3. 直接記憶體,看樣子也與Native方法有關,自己沒遇到過,日後研究。
  4. 都是存在方法區,為啥靜態方法、靜態變數不能通過物件訪問,而常量可以? 已消滅
  5. 常量池與執行時常量池?已消滅