1. 程式人生 > >jvm學習筆記(3)——java物件的記憶體分配和物件的回收(GC)

jvm學習筆記(3)——java物件的記憶體分配和物件的回收(GC)

引言:    

    之前的文章已經提過,java物件例項是存放在堆上的,至於是在伊甸區、存活區還是老年區,這些都是從物件回收(GC)角度來進行的邏輯劃分。所以我們先說物件的回收(GC),然後再依據GC的策略來說明新的物件具體在哪個區生成。

GC(Garbage Collection):

    垃圾回收,指的就是jvm佔用記憶體的回收。那麼需要回答3個問題:

  • 哪些記憶體需要回收?——>可達性分析演算法。
  • 什麼時候回收?——>簡單的來說,伊甸區的空間不足發生新生代GC(Minor GC),老年代空間不足的時候發生老年代GC(Major GC / Full GC)
  • 如何回收?——>通過垃圾回收器,jdk8預設的是UseParallelGC(PS scavenge + Serial Old),還有UseConMarkSweepGC(ParNew + CMS + Serial Old),以及UseG1GC(G1)。

1、可達性分析演算法:以一系列成為“GC Root”的物件最為起始點,當一個物件沒有到達GC Roots的引用鏈條,就判定這個物件為可回收的。

    GC Roots物件:

  • 虛擬機器棧(棧幀中的本地變量表)中引用的物件。
  • 方法區中類靜態屬性引用的物件。
  • 方法區中常量引用的物件。
  • 本地方法棧中JNI(即Native方法)引用的物件。

2、垃圾收集演算法(分代收集):

  • 新生代,物件存活率較低,複製演算法。
  • 老年代,物件存活率較高,標記-整理演算法、標記-清除演算法。

3、垃圾收集器:

新生代收集器:

  • Serial收集器:採用“複製”演算法,暫停使用者執行緒,單執行緒收集。
  • ParNew收集器:採用“複製”演算法,暫停所有使用者執行緒,採用多執行緒並行收集。和CMS老年代收集器搭配使用。關注點:GC時使用者執行緒的停頓時間。
  • Parallel Scavenge收集器:採用“複製”演算法,和ParNew收集器類似,但關注點不同。關注點:高吞吐量。

老年代收集器:

  • Serial Old 收集器:採用“標記-整理”演算法,暫停使用者執行緒,單執行緒收集。和Parallel Scavenge收集器搭配使用。
  • Parallel Old收集器:採用“標記-整理”演算法,暫停使用者執行緒,多執行緒並行收集。和Parallel Scavenge收集器搭配使用。
  • CMS(Concurrent Mark Sweep)收集器:採用“標記-清除”演算法,不暫停使用者執行緒,多執行緒併發收集。與ParNew收集器搭配使用。

新一代收集器:

    G1(Garbage-First)收集器:

  • GC工作時為並行,GC與使用者執行緒為併發;
  • 可獨立管理整個GC堆,不需要與其他GC收集器配合使用;
  • 空間整合:整理上看是“標記-整理”演算法實現的,從區域性(兩個Region之間)上看是基於“複製”演算法實現的。

總結:

  1. ParallelScavenge關注的是高吞吐量;
  2. CMS關注的是低停頓時間;
  3. G1關注的是使用時間相對較短的停頓來達到很高的吞吐量,CMS的替代品。

4、GC發生時間:

    (1)MinorGC:大多數情況下,物件在新生代Eden區分配。當Eden區沒有足夠空間時,進行一次minorGC。如果是大物件,直接在老年代分配。

    (2)FullGC:

        a.系統主動呼叫System.gc(),不一定立即執行;

        b.老年代空間不足;

        c.方法區空間不足;

        d.通過Minor GC後進入老年代的平均大小大於老年代的可用記憶體;

        e.由Eden區、From Space區向To Space區複製時,物件大小大於To Space可用記憶體,則把該物件轉存到老年代,且老年代的可用記憶體小於該物件大小。

參考資料:《深入JAVA虛擬機器》