Java記憶體管理機制

WesleyWang97發表於2018-05-08

記憶體劃分割槽域

方法區(Method Area), 虛擬機器棧(VM Stack), 本地方法棧(Native Method Stack), 堆(Heap), 程式計數器(Program Counter Register)
1. 程式計數器(Program Counter Register)
執行緒私有的.當前執行緒所執行的位元組碼的行號指示器.通過改變這個計數器的值來選取下一條需要執行的位元組碼指令.
2. 虛擬機器棧(VM Stack)
執行緒私有的,生命週期與執行緒相同.每個方法被執行的時候都會建立一個棧幀(Stack Frame)用於儲存區域性變數,操作棧,動態連結,方法出口等資訊.每一個方法被呼叫直至執行完成的過程,對應著一個棧幀在虛擬機器棧中從入棧到出棧的過程.
3. 本地方法棧(Native Method Stacks)
與虛擬機器棧發揮的作用非常相似.區別是虛擬機器棧執行Java方法(也就是位元組碼)服務,而本地方法棧則是為虛擬機器使用到的Native方法服務.
4. 堆(Heap)
最大的一塊,所有執行緒共享的一塊記憶體,虛擬機器啟動時建立.唯一目的就是存放物件例項.垃圾收集器管理的主要區域,很多時候也被稱作"GC堆"(Garbage Collected Heap)
5. 方法區(Method Area)
各個執行緒共享區域,儲存已被虛擬機器載入的類資訊,常量,靜態變數,即時編譯器編譯後的程式碼等資料.執行時常量池(Runtime Constant Pool)是方法區的一部分,存放編譯期生成的各種字面量和符號引用

物件訪問

Object obj = new Object();

Object obj將會反映到Java棧的本地變數表中,作為一個reference型別資料出現.而”new Object()”這部分則會反映到Java堆中,形成了一塊儲存了Object型別所有例項資料的結構化記憶體.而reference型別訪問物件的方式有兩種:
- 使用控制程式碼,Java堆中將會劃分出一塊記憶體作為控制程式碼池,reference儲存控制程式碼地址
- 使用指標,reference中直接儲存的就是物件地址.主要虛擬機器(Sun HotSpot)使用的這一種

垃圾回收(GC)

物件已死

  1. 引用計數法(Reference Counting)
    引用時,計數器加1,失效時減1.簡單高效,但是無法解決相互迴圈引用的問題.
  2. 根搜尋演算法(GC Roots Tracing)
    主流的方法.通過一系列名為”GC Roots”的物件作為起始點,從這些節點開始向下搜尋,搜尋所走過的路徑稱為引用鏈(Reference Chain),當一個物件沒有任何引用鏈相連時,則證明物件是不可用的.可作為GC Roots的物件有以下幾種:
    • 虛擬機器棧(棧幀中的本地變數表)中的引用的物件
    • 方法區中的類靜態屬性引用的物件
    • 方法區中的常量引用的物件
    • 本地方法棧中JNI的引用的物件(類似於第一種)
      這裡寫圖片描述

何時回收

一個物件死亡,至少要經歷兩次標記過程:第一次判斷是否有與GC Roots相連線的引用鏈,如果沒有被執行過finalize指令,則會執行,被放置在一個F-Queue中,由虛擬機器建立的Finalizer執行緒執行.GC將對F-Queue中的物件進行得二次小規模標記.

回收方法區

方法區(或者HotSpot虛擬機器中的永久代)的回收的"價效比"一般比較低.主要回收廢棄常量和無用的類

垃圾收集演算法

  1. 標記-清除(Mark-Sweep)演算法
    分為標記,清除兩個階段.首先標記出所有需要回收的物件,在標記完成後統一回收所有被標記的物件.
    有兩個缺點:(1)效率 (2)空間,容易造成碎片

  2. 複製(Copying)演算法
    將可用記憶體按照容量劃分為大小相等的兩塊,每次只使用其中的一塊,當這一塊的記憶體用完了,就將存活著的物件複製到另一塊上面,然後再把已使用過的記憶體空間一次清理掉.這樣實現簡單,但是代價是記憶體縮小到原來的一般,空間代價較高.

這裡寫圖片描述

  1. 標記-整理演算法
    複製收集演算法在物件存活率較高的時候就要執行較多的複製操作,效率變低,而且空間浪費高.標記整理演算法是讓所有的存活物件都向一端移動,然後直接清理掉端邊界外的記憶體.

這裡寫圖片描述

  1. 分代收集演算法
    根據物件的存貨週期劃分為幾塊.一般把堆分為新生代(Young Generation)和老年代(Old Generation).根據各個年代的特點採用最適當的收集演算法.在新生代如果有大批物件死去,少量存活,就採用複製演算法,只需要少量的複製就可以完成收集.而老年代中則採取"標記-清理"或者"標記-整理"演算法來回收

垃圾收集器

垃圾收集演算法的具體實現
這裡寫圖片描述

物件分配回收策略

  1. 物件優先在新生代Eden分配.當Eden區沒有足夠的空間進行分配時,虛擬機器將發起一次Minor GC.(新生代GC為MinorGC; 老年代GC為Major GC/Full GC)
  2. 大物件直接進入老年代.避免在Eden區以及兩個Survivor區之間發生大量的記憶體拷貝.
  3. 長期存活的物件進入老年區.給每個物件定義一個物件年齡(Age)計數器,年齡增加到一定程度時(預設為15歲),就晉升到老年代
  4. 動態物件年齡判定.如果Survivor空間中相同年齡所有物件大小的總和大於Survivor空間的一半,年齡大於或等於該年齡的物件就可以直接進入老年代.
  5. 空間分配擔保.如果晉升到老年代的平均大小大於老年代的剩餘空間大小,則改為直接進行一次Full GC.

相關文章