1. 程式人生 > >執行時資料區組成_深入JVM(一)

執行時資料區組成_深入JVM(一)

執行時資料區

        JVM在執行java程式時,會把其所管理的記憶體劃分成多個區域,每個區域都有不同用途,每個區域的建立和銷燬時間也不同.這每塊記憶體都屬於執行時資料區域.

        這些區域有程式計數器,方法區,堆,虛擬機器棧,本地方法棧

程式計數器

        程式計數器是當前執行緒所執行的位元組碼行號指示器 . 它所用記憶體空間很小,是執行緒私有的 .

        它的作用是記錄當前執行緒執行到位元組碼指令的地址(class檔案的哪個地方),若該執行緒等待 ,處理器時間片重新排程到該執行緒,程式計數器可以讓處理器知道接下來要執行哪行位元組碼指令.

        分支,迴圈,跳轉,異常處理,執行緒回覆等都需要以來程式計數器來完成

Java虛擬機器棧

        虛擬機器棧是執行緒私有的,其生命週期與執行緒相同

        在棧中,每執行一個方法前都會建立一個棧幀,來儲存區域性變量表,運算元棧,動態連結.方法出口等資訊 .每個方法從呼叫到完成,就對應著棧中一個棧幀的壓棧到彈出的過程.

        棧幀的區域性變量表用來儲存8種基本資料型別,reference型別(物件的引用),returnAddress型別(方法結束後執行的位元組碼指令的地址) . 儲存在區域性變量表的資料是以32位的Slot變數空間進行儲存 , double和float型別則需要兩個slot空間儲存.

        一個方法對應的棧幀中區域性變量表所需記憶體空間早已在編譯期間就分配完成 , 當進入一個方法,虛擬機器棧對應壓入一個棧幀,次棧幀區域性變量表空間大小完全確定

本地方法棧

        和虛擬機器棧相似,本地方法棧用來服務Native方法

        在我們最常用的HotSpot虛擬機器中,本地方法棧與java虛擬機器棧合二為一

        Java堆是一塊執行緒共享的記憶體區域 , 它在虛擬機器啟動時分配建立 , 它是JVM記憶體裡最大的一塊記憶體了,但是它的目的只有一個 ---- 存放物件例項 .

        堆大概可以分為新生代和老年代 .再分的細一些為 Eden區 ,From Survivor區 ,To Survivor區和老年代 . java堆也是垃圾收集(GC)的主要區域 ,GC方式在每個帶都有不同的規則(分代收集演算法).

        Java堆為了更快的分配,更好的回收記憶體,可能會劃分出多個執行緒私有的分配緩衝區,來提升管理記憶體的速度 .

        Java堆可以處於物理上不連續的記憶體空間中 , 只需要邏輯上連續就好 .

方法區

        虛擬機器規則定義方法區應是儲存已被虛擬機器載入的類資訊,常量,靜態變數,即時編譯器編譯後的程式碼等資料 . 是執行緒共享的內群區域 .

        這部分割槽域比較特殊,虛擬機器規範這部分割槽域屬於堆 , 但是其作用又與堆有較大差異 .虛擬機器如何實現方法區,則不受虛擬機器規範約束. HotSpot為例 , jdk1.7之前,方法區為永久代,其垃圾回收受java堆GC分帶收集演算法管理 . 1.7將String常量池移入堆中 , jdk1.8中永久代被完全移除 ,將類載入資訊放入一個執行緒共享的元空間內.

        JRockit與HotSpot合併,這樣表面上是避免永久區的OOM,實際是為了更好的與JRockit合併 , JRockit 和 J9虛擬機器就沒有永久代的概念.

 

======================================================================

執行時常量池

        用來存放編譯生成的字面量和符號引用 , 是方法區的一部分

直接記憶體

        直接記憶體不屬於虛擬機器規範中定義的記憶體區域,當然不屬於執行時資料區.

        NIO使用Native函式庫直接分配堆外記憶體 , 然後通過一個DirectByteBuffer物件作為這塊記憶體的引用,可以大幅度減輕堆的負擔,提高虛擬機器效能 .