jvm之記憶體分配策略
GC日誌的基本格式,如下是一次GC的日誌:
本地環境是JDK1.8
首先開頭的[GC和[Full GC表示了這一次GC的型別,如果有full,表示發生了stop the world。[GC (Allocation Failure) [PSYoungGen: 2536K->488K(2560K)] 5501K->5511K(9728K), 0.0058699 secs] [Times: user=0.03 sys=0.00, real=0.02 secs] [Full GC (Ergonomics) [PSYoungGen: 488K->0K(2560K)] [ParOldGen: 5023K->4855K(7168K)] 5511K->4855K(9728K), [Metaspace: 3483K->3483K(1056768K)], 0.0658519 secs] [Times: user=0.11 sys=0.00, real=0.06 secs] [GC (Allocation Failure) [PSYoungGen: 2048K->512K(2560K)] 6903K->6877K(9728K), 0.0037400 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
[]內部的資料a->b(c),a表示GC前該區域佔用記憶體大小,b表示GC後該區域佔用記憶體大小,c表示該區域的總記憶體大小。
[]外部的資料a->b(c),a表示GC前堆使用記憶體大小,b表示GC後堆佔用記憶體大小,c表示該堆的總記憶體大小。
後面的事件分別表示使用者態消耗的CPU時間、核心態消耗的CPU時間和操作從開始到結束經過的牆鍾時間。
CPU時間與核心時間區別是,核心時間包含非運算耗時,執行緒阻塞、I/O等。如果是多CPU,CPU時間會累加這些CPU時間,所以user時間有可能比real時間大。
垃圾回收相關的引數設定:
UseSerialGC:虛擬機器執行在Client模式下時預設值,使用Serial+Serial Old收集器組合
Client模式和Server模式:Server模式啟動慢,但是執行後會進行優化。預設情況下虛擬機器會判斷伺服器,如果CPU數量大於2,記憶體大於2G會以server模式啟動。預設情況下Client模式-Xms1m,-Xmx10m;Server模式-Xms128m,-Xmx1024m。
UseParNewGC:使用ParNew+Serial Old收集器組合
UseConcMarkSweepGC:使用ParNew+GMS+Serial Old組合
useParallelGC:Server模式的預設值,使用Parallel Scavenge+Serial Old組合
記憶體分配策略:
一般情況下,物件分配到Eden區。當Eden中沒有足夠空間時,進行一次Minor GC。
Minor GC:新生代GC
Major GC/Full GC:老年代GC
大物件會直接進入老年代,大物件只需要大量連續空間的物件,-XX:PreTenureSizeThreshold用來控制大物件的大小,大於這個值的物件直接分配到老年代。
長期存活的物件進入老年代,物件出生在Eden區沒經過一次Minor GC後仍然存活,並且被Survivor容納,則年齡加1。當年齡到達一定程度,預設15,晉升到老年代,通過-XX:MaxTenuringThreshold設定。
動態年齡判斷:虛擬機器為了更好的適應不同程式的記憶體狀況,虛擬機器並不會永遠要求到達-XX:MaxTenuringThreshold設定的年齡才進升,如果Survivor空間中相同年齡的所有物件大小大於Survivor空間的一半,年齡大於或等於該年齡的物件直接進入老年代。
空間分配擔保:因為新生代採用複製演算法,如果一次GC後所有物件都存活,那就需要老年代進行擔保,把Survivor無法容納的物件直接進入老年代。所以在進行Minor GC時,會先檢查老年代最大連續可用空間是否大於新生代所有物件的總空間,如果成立,則Minor GC是安全的。如果不是,則會檢查老年代的最大連續可用空間是否大於歷次晉升到老年代物件的平均大小,如果大小,則進行一次Minor GC,儘管有風險。如果小於,進行Full GC。