jvm學習筆記(3)——java物件的記憶體分配和物件的回收(GC)
阿新 • • 發佈:2018-12-16
引言:
之前的文章已經提過,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之間)上看是基於“複製”演算法實現的。
總結:
- ParallelScavenge關注的是高吞吐量;
- CMS關注的是低停頓時間;
- 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虛擬機器》