JVM(一)——Java 執行時的資料區域

zhoupq發表於2017-04-06

JVM(一)——Java 執行時的資料區域


JVM(一)——Java 執行時的資料區域

程式計數器

程式計數器(Program Counter Register)是一塊較小的記憶體空間,它可以看作是當前執行緒所執行的位元組碼的行號指示器。

  通俗地講,執行緒執行的任務在計算機語言中,被當做是一條條的指令。執行緒需要一個計數器來幫助它標記執行了什麼指令,以及選取下一條指令。

  每條執行緒被CPU執行之後,需要切換下一條,為了使執行緒能恢復到正確的執行位置,每條執行緒都需要有一個獨立的程式計數器,各執行緒之間的計數器互不影響,獨立儲存。

  這一塊記憶體區域為“執行緒私有”的記憶體。

Java 虛擬機器棧

Java 虛擬機器棧(Java Virtual Machine Stacks)也是執行緒私有的,生命週期與執行緒相同,因為它描述的是Java方法執行的記憶體模型。

  Java方法執行的記憶體模型:每個方法在執行的同時都會建立一個棧幀(Stack Frame,方法執行時的基礎資料結構)用於儲存區域性變數表、運算元棧、動態連結、方法出口等資訊。

  每個方法從呼叫直至執行完成的過程,就對應著一個棧幀在虛擬機器棧中入棧到出棧的過程。

  在Java虛擬機器的規範中,對這個區域規定了兩種異常情況:

  • StackOverflowError
      如果執行緒請求的棧深度大於虛擬機器所允許的深度,將丟擲 StackOverflowError異常
  • OutOfMemoryError
      如果虛擬機器棧在擴充套件的時無法申請到足夠的記憶體,就會丟擲 OutOfMemoryError異常

本地方法棧

本地方法棧(Native Mrthod Stack)與虛擬機器棧發揮的作用非常相似,他們之間的區別:

  • 虛擬機器棧為虛擬機器執行java方法(也就是位元組碼)服務
  • 本地方法棧則為虛擬機器使用到的Native方法服務

  與虛擬機器一樣,本地方法棧區域也會丟擲 StackOverflowError 和 OutOfMemeoryError 異常。

Java 堆

Java 堆(Java Heap)是Java虛擬機器鎖管理的記憶體中最大的一塊,Java堆是被所有執行緒共享的一塊記憶體區域,在虛擬機器啟動時建立。此記憶體區域的唯一目的就是存放物件例項

  Java 堆可以處於物理上不連續的記憶體空間中,只要邏輯上是連續即可。在實現時,既可以實現成固定大小的,也可以是可擴充套件的(通過-Xmx 和 -Xms 控制)。如果在堆中沒有記憶體完成例項分配,並且堆也無法再擴充套件時,將會丟擲 OutOfMemoryError 異常。

  此外,Java 堆是垃圾收集器器管理的主要區域。

方法區

方法區(Method Area)與 Java 堆 一樣,是各個執行緒共享的記憶體區域,它用於儲存已被虛擬機器載入的類資訊、常量、靜態變數、即時編輯器編譯後的程式碼等資料。

  方法區是堆的一個邏輯部分,但是它與java堆又是不同的,所以它有了一個別名——非堆(Non-Heap)。

  方法區中的記憶體一般不會被 GC 回收,GC 也難回收,所以被取名為“永久代”,意思是永久存在。這區域的記憶體回收目標主要是針對常量池的回收和對類的解除安裝。但是“永久代”中的資料並非真的永久存在,只是回收比較麻煩。

  根據 Java 虛擬機器規範的規定,當方法區無法滿足記憶體分配需求時,將丟擲 OutOfMemoryError 異常。

小結

  執行緒共享區域:

  • Java 堆
  • 方法區

  執行緒私有區域:

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

  可能丟擲 OutOfMemoryError 異常:

  • Java 虛擬機器棧
  • 本地方法棧
  • Java 堆
  • 方法區

  可能丟擲 StackOverflowError 異常:

  • Java 虛擬機器棧

相關文章