1. 程式人生 > >JVM原理及優化之二:記憶體管理

JVM原理及優化之二:記憶體管理

1. 記憶體分配策略:

1. 物件優先在Eden分配 2. 大物件直接進入老年代 3. 長期存活物件將進入老年代(當它的年齡增加到一定程度 (預設為15歲 ),就會被晉升到老年代中 。物件晉升老年代的年齡閾值,可以通過引數 -XX:MaxTenuringThreshold來設定) 4. 動態物件年齡判定(如果在 Survivor空間中相同年齡所有物件大小的總和大於 Survivor空間的一半,那麼年齡大於或等於該年齡的物件就直接進行老年代,無須等到 MaxTenuringThreshold中要求的年齡) 5. 空間分配擔保     a> 在發生Minor GC時,虛擬機器會檢測之前每次晉升到老年代的平均大小是否大於老年代剩餘空間的大小,如果大於,則改為直拉進行一次Full GC。如果小於,則檢視HandlePromotionFailure設定是否允許擔保失敗;如果允許,那隻會進行Minor GC;如果不允許,則要改為進行一次Full GC。     b> 新生代使用複製收集演算法,但為了提高記憶體利用率,只使用其中一個Survivor空間來作為輪換備份,因此當出現大量物件在Minor GC後仍然存活的情況時,最需要老年代進行分配擔保,讓Survivor空間無法容納的物件直接進入老年代。     c> 取平均值進行比較仍然是一種動態概率的手段,也就是說如果某次Minor GC存活的物件突增,遠高於平均值的話,依然會導致擔保失敗(HandlePromotionFailure)。如果出現了HandlePromotionFailure,那隻好在失敗後重新發起一次Full GC。雖然擔保失敗時繞圈子是最大的,但是大部情況下還是會將HandlePromotionFailure開關開啟,避免Full GC過於頻繁。

2. 垃圾收集行為分類:

備註: 1、concurrent: 併發, 多個執行緒協同做同一件事情(有狀態) 2、parallel: 並行, 多個執行緒各做各的事情(互相間無共享狀態)

3. 垃圾收集演算法:

3.1 標記清除演算法

標記-清除(Mark-Sweep)演算法是最基礎的演算法,它分為”標記”和”清除”兩個階段:首先標記出所有需要回收的物件,在標記完成後統一回收掉所有被標記的物件。之所以說它是最基礎的收集演算法,是因為後續的收集演算法都是基於這種思路並對其缺點進行改進而得到的。處理過程: 標記清除收集器停止所有的工作,從根掃描每個活躍的物件,然後標記掃描過的物件,標記完成以後,清除那些沒有被標記的物件

優點: 1、解決迴圈引用的問題 2、不需要編譯器的配合,從而就不執行額外的指令缺點: 1、每個活躍的物件都要進行掃描,標記和清楚過程的效率都不高,收集暫停的時間比較長。 2、另外一個是空間問題,標記清楚後會產生大量不連續的記憶體碎片,空間碎片太多可能會導致,當程式在以後的運 行 過程中需要分配較大物件時無法找到足夠連續的記憶體空間而不得不提前出發另一次垃圾收集動作。

3.2 複製演算法

為了解決效率問題,一種稱為複製(Copying)的收集演算法就出現了,它將可用記憶體按容量劃分為大小相等的兩塊,每次只是用其中一塊。當這一塊的記憶體用完了,就將還存活著的物件複製到另外一塊上面,然後再把已使用過的記憶體空間一次清理掉收集過程:

回收時,將 Eden和Survivor 中還存活著的兌現個一次性地拷貝到另外一塊 Survivor空間上,最後清理掉Eden和剛才用過的 Survivor的空間。HotSpot虛擬機器預設 Eden和Survivor的大小比例是 8:1,也就是每次新生代中可用記憶體空間為整個新生代容量的 90%,只有10%的記憶體是會被浪費的優點: 1、只掃描可以到達的物件,不需要掃描所有的物件,從而減少了應用暫停的時間缺點: 1. 需要額外的空間消耗,某一個時刻,總是有一塊記憶體處於未使用狀態 2. 複製物件需要一定的開銷

3.3 標記整理演算法

複製演算法不適用於老年代: 在物件存活率較高時就要執行較多的複製操作,效率將會貶低。 更關鍵的是,如果不想浪費 50% 的空間,就需要有額外的空間進行分配擔保,以應對被使用的記憶體中所有物件都 100% 存活的極端情況,所以在老年代一般不能直接選用這種演算法 。

根據老年代的特點,有人?出了另外一種 ”標記- 整理”演算法,標記過程仍然與標記 -清楚演算法一樣,但是後續步驟不是直接對可回收物件進行清理,而是讓所有存活的物件都向一端移動,然後直接清理掉端邊界意外的記憶體。執行過程: 1、第一個階段,掃?所有活躍的物件(即有用物件),並標記所有活躍的物件 2、第二個階段,清除未標記的物件,然後將活躍的的物件複製到堆得底部。

4. GC執行條件:

5. GC效能指標:

下面的幾個指標用來衡量GC的執行效能,包括: 1) 吞吐量(Throughput):在一段長時間內,沒有花費在垃圾收集上的時間所佔的比例。 2) 垃圾收集代價(Garbage Collection Overhead):與吞吐量相反,垃圾收集時間所佔的比例。 3) 暫停時間(Pause Time):當執行垃圾收集時,應用程式被迫暫停的時間長度。 4) 垃圾收集頻率(Frequency Of Collection):相對於應用程式的執行,垃圾收集執行的頻率。 5) 覆蓋區(Footprint):一種大小的度量,如堆的大小。 6) 敏捷度(Promptness):指從一個物件成為垃圾時到該物件所佔用的記憶體被回收時之間的時間長度。