對象存活判定算法
- 引用計數(shù)算法
虛擬機并不是通過引用計算算法來判斷對象是否存活的 - 可達性分析算法
基本思路:通過一系列的稱為"GC Roots"的對象作為起始點,從這些節(jié)點開始向下搜索,搜索所走過的路徑稱為引用鏈,當一個對象到GC Roots 沒有任何引用鏈相連,則證明該不可用。
JDK 1.2 之后,引用分為強引用、軟引用、弱引用、虛引用,4種。
垃圾收集算法:
- 標記-清除算法(Mark-Sweep), 最基礎的收集算法。不足:效率問題,標記和清除兩個過程的效率都不高;空間問題,標記清除后會產(chǎn)生大量不連續(xù)的內存碎片,空間碎片太多可能會導致以后在程序運行過程中需要分配較大對象時,無法找到足夠的連續(xù)內存而不得不提前出發(fā)另一次垃圾收集動作。
- 復制算法(Copying), 為解決效率問題.
IBM公司專門研究,新生代中的對象98%是"朝生夕死",所以并不需要1:1的比例來劃分內存空間,而是將內存分為較大的Eden(80%)空間和兩塊較小的Survicor(10%)空間,每次使用Eden和其中一塊Survivor。當回收時,將Eden和Survivor中還存活的對象一次性復制到另一塊Survivor空間上,最后清理掉Eden和剛用過的Survivor空間。
缺陷:1. 對象存活率較高時,就要進行較多的復制操作,效率會變低。2. 需要額外的空間進行分配擔保。 - 標記-整理算法(Mark-Compact)
不對可回收對象進行清理,而是所有存活的對象向一端移動,然后直接清理掉端邊界以外的內存。 - 分代收集算法
根據(jù)對象存活周期不同將內存劃分為幾塊。一般是把Java堆分為新生代和老年代,這樣根據(jù)各年代特點采用最適當?shù)氖占惴ā?/li>
算法執(zhí)行效率保證
- 枚舉根節(jié)點
OopMap數(shù)據(jù)結構:類加載完,HotSpot就把對象內什么偏移量上是什么類型數(shù)據(jù)計算出來,在JIT編譯過程中,也會在特定的位置記錄下棧和寄存器中哪些位置是引用的。GC掃描時就可以直接得知這些信息。 - 安全點(Safepoint)
- 安全區(qū)域(Safe Region)
垃圾收集器
- Serial 單線程,簡單高效,新生代中使用
- ParNew :Serial多線程版本
- Parallel Scavenge 新生代收集器
目的是達到一個可控制的吞吐量。吞吐量:CPU用于運行用戶代碼的時間與CPU總消耗時間的比值。=運行用戶代碼時間/(運行用戶代碼時間+垃圾收集時間) - CMS (Concurrent Mark Sweep)JDK1.5收集老年代,一種以獲取最短回收停頓時間為目標。使用標記-清除算法。
缺點:
- CPU資源非常敏感
- 無法處理浮動垃圾,可能出現(xiàn)"Concurrent Mode Failure"失敗而導致另一次Full GC的產(chǎn)生。
- 由于使用了標記-清除算法,收集結束時有大量空間碎片產(chǎn)生,提前觸發(fā)一次Funll GC.
- G1(Garbage First) JDK 7u4,面向服務端應用的垃圾收集器
特點:
- 并行與并發(fā),使用多個CPU來縮短Stop-The-World 停頓的時間,G1收集器可以通過并發(fā)方式讓程序繼續(xù)執(zhí)行。
- 分代收集
- 空間整合 G1運作期間不會產(chǎn)生內存空間碎片,收集后能提供規(guī)整的可用內存。
- 可預測的停頓。
- Serial Old 老年代中使用,使用標記-整理算法。
- Parallel Old 是 Parallel Scavenge老年代版本