1. 程式人生 > >JVM學習筆記(一)執行時資料區

JVM學習筆記(一)執行時資料區

執行時資料區

    java虛擬機器在執行java程式的過程中會把所管理的記憶體劃分為若干個不同的資料區域。這些區域都有各自的用途,以及建立和銷燬的時間。

  1. 有的區域隨著虛擬機器程序的啟動而存在,隨虛擬機器程序的退出而銷燬;
  2. 有的區域則依賴使用者執行緒的啟動和結束而建立和銷燬。

java虛擬機器所管理的記憶體將會包括以下幾個執行時資料區域

java虛擬機器執行時資料區

程式計數器

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

    由於Java虛擬機器的多執行緒是通過執行緒輪流切換並分配處理器執行時間的方式來實現的,在任何一個確定的時刻,一個處理器(對於多核處理器來說是一個核心)都只會執行一條執行緒中的指令。因此,為了切換執行緒後能恢復到正確的執行位置,每條執行緒都需要一個獨立的程式計數器,各條執行緒之間計數器互不影響,獨立儲存,稱這塊區域為“執行緒私有

”的記憶體。

    如果執行緒正在執行的是一個java方法,這個程式計數器記錄正在執行的虛擬機器位元組碼指令的地址;如果正在執行的是Native方法,這個程式計數器的值為空(Undefined)。此記憶體區域是唯一一個在Java虛擬機器規範中沒有規定任何OutOfMemoryError情況的區域。

虛擬機器棧

  • 執行緒私有,生命週期與執行緒相同。
     
  • 虛擬機器棧描述的是java方法執行的記憶體模型:每次方法呼叫都會建立一個幀棧,用於儲存區域性變量表、運算元棧、動態連結、方法出口等資訊。每一個方法從呼叫直至執行完成的過程,就對應著一個幀棧在虛擬機器棧中入棧到出棧的過程。

  • JVM Stack 異常情況:
     StackOverflowError:當執行緒請求分配的棧容量超過JVM允許的最大容量時丟擲

     OutOfMemoryError:如果JVM Stack可以動態擴充套件,但是在嘗試擴充套件時無法申請到足夠的記憶體去完成擴充套件,或者在建立新的執行緒時沒有足夠的記憶體去建立對應的虛擬機器棧時丟擲。

本地方法棧

  • 為虛擬機器執行Native方法服務

  • 和虛擬機器棧一樣,同樣會丟擲StackOverflowError和OutOfMemoryError異常

Java堆

  • 執行緒共享

  • 存放物件例項

  • 虛擬機器啟動時建立

  • Java堆的容量可以是固定大小,也可以隨著需求動態擴充套件,並在不需要過多空間時自動收縮。

  • Java堆所使用的記憶體不需要保證是物理連續的,只要邏輯上是連續的即可。

  • 如果在隊中沒有記憶體完成例項分配,並且堆也無法再擴充套件時,將會丟擲OutOfMemoryError異常

    方法區

  • 執行緒共享

  • 用於儲存已被虛擬機器載入的類資訊、常量、靜態變數、即時編譯器編譯後的程式碼等資料

  • 虛擬機器啟動時建立

  • JDK6時,String等常量資訊置於方法區
    JDK7時,已經移動到了堆

  • 該區域的記憶體回收比較少出現,主要是針對常量池的回收和型別的解除安裝

執行時常量池

    執行時常量池(Runtime Constant Pool)是方法區的一部分。Class檔案中除了有類的版本、欄位、方法、介面等描述資訊外,還有一項資訊是常量池。用於存放編譯期產生的各種字面常量符號引用,這部分內容將在類載入後進入方法區的執行時常量池中存放。

    既然執行時常量池是方法區的一部分,自然會受到方法區的限制,當常量池無法再申請到記憶體時會丟擲OutOfMemeoryError異常。