1. 程式人生 > >JVM 執行時資料區詳解

JVM 執行時資料區詳解

 

     1、PC暫存器(執行緒獨有):全稱是程式計數暫存器,它記載著每一個執行緒當前執行的JAVA方法的地址,如果是當前執行的是native方法,則程式計數器會是一個空地址。它的作用就是用來支援多執行緒,執行緒的阻塞、恢復、掛起等一系列操作。這個記憶體區域是唯一一個在虛擬機器中沒有規定任何OutOfMemoryError情況的區域。

 

     2、JAVA虛擬機器棧(執行緒獨有)JAVA虛擬機器棧是在建立執行緒的同時建立的,生命週期與執行緒相同。每個方法被執行的時候都會同時建立一個棧幀,用於儲存區域性變量表、操作棧、動態連結、方法出口等資訊。每個方法從被呼叫到執行完成,就對應著一個棧幀在虛擬機器棧中從入棧到出棧的過程。

  • 棧幀:簡單點說,可以解釋為是一個方法執行時,臨時資料的儲存區域,具體點說,它裡面包括了資料和部分的過程結果,與此同時,它又肩負著處理方法返回值、動態連結以及異常分派的任務。棧幀是隨著方法的建立而建立,隨著方法的結束而銷燬,如果方法丟擲異常,也算方法結束。然而在每一個棧幀中,都有著自己的區域性變量表以及運算元棧以及對當前類的執行時常量池的引用。
  • 區域性變量表:在編譯時期就寫入了class檔案當中,所需的記憶體空間在編譯期間完成分配。簡單的理解,可以將它理解為一個物件陣列,而裡面按照索引0到length-1分別對應於每一個區域性變數,特別的,如果是例項方法的區域性變量表,第0個區域性變數會是一個指向當前例項的引用,也就是this關鍵字,其餘的區域性變數則從索引1開始。
  • 運算元棧它是一個後進先出(LIFO)棧,而它的長度也是在編譯時期就寫入了class檔案當中,是固定的。它的作用就是提供位元組碼指令操作變數計算的空間,比如簡單的,對於int a=9這句話來說,就需要先將9壓入運算元棧,再將9賦給a這個變數。

 

     3、本地方法棧(執行緒獨有)它用來支援native方法的執行。如果JAVA虛擬機器是使用的其它語言實現指令集直譯器的時候,也會用到本地方法棧。如果某個虛擬機器實現的native方法介面是使用C連線模型的話,那麼它的本地方法棧就是C棧。

    public static native long currentTimeMillis();

 

     4、JAVA堆(全域性共享)堆隨著JAVA虛擬機器的啟動建立,儲存著所有物件例項以及陣列物件,而且內建了“自動記憶體管理系統”,也就是我們常說的垃圾蒐集器(GC)。JAVA堆中的記憶體釋放是不受開發人員控制的,完全由JAVA虛擬機器一手操辦。對於JAVA虛擬機器如何實現垃圾蒐集器,JAVA虛擬機器規範沒有明確的規定,也正因如此,我們平時使用的JAVA虛擬機器中提供了許多種垃圾蒐集器,它們採用不同的演算法以及實現方式,已滿足多方面的效能需求。

由於現在收集器基本採用分代手機演算法,所以JAVA堆還可以細分為“新生代”和“老年代”;新生代再細緻一點的有Eden空間、From Survivor空間、To Survivor空間等,一般情況,Eden空間佔80%,Survivor各佔10%。

 

     5、方法區(全域性共享):方法區也是堆的一個組成部分,也叫非堆,它主要儲存的是執行時常量池、靜態變數、類資訊、欄位資訊、方法資訊、構造方法與普通函式的位元組碼內容以及一些特殊方法。垃圾收集行為在這個區域是比較少出現的,主要針對常量池和型別解除安裝。在HotSpot虛擬機器中,用永久代來實現方法區,將GC分代收集擴充套件至方法區,但是這樣容易遇到記憶體溢位的問題。JDK1.7中,已經把放在永久代的字串常量池移到堆中。JDK1.8撤銷永久代,引入元空間(動態擴容)。

執行時常量池是方法區的一部分,用於存放編譯期生成的各種字面量和符號引用,這部分內容將在類載入後存放到方法區的執行時常量池中。執行期間也可以將新的常量放入池中,比如String類的intern()方法。