JVM实战与原理---内存回收策略
JVM實戰(zhàn)與原理
目錄
內(nèi)存回收策略
1. 堆的劃分
2. 判斷對象是否存活的算法介紹
2.1 引用計數(shù)算法
2.2?可達性分析算法
3. 可回收的內(nèi)存區(qū)域清理的算法介紹
3.1?標記-清除算法
3.2?復制算法
3.3?標記-整理算法
3.4 分代收集算法
4. 垃圾收集器
4.1?Serial收集器
4.2 ParNew收集器
4.3 Parallel Scavenge收集器
4.4 Serial Old收集器
4.5?Parallel Old收集器
4.6 CMS收集器
4.7 G1收集器
內(nèi)存回收策略
章節(jié)目的:介紹垃圾收集的算法有哪些?JDK提供的垃圾收集器的特點及運作原理?
引言:當內(nèi)存空間被動態(tài)分配時,同樣的,我們就需要進行回收,這就是我們常說的GC,垃圾收集技術。
那么我們?yōu)槭裁葱枰獙W習內(nèi)存回收和GC呢?答案:當我們的程序出現(xiàn)內(nèi)存泄漏或溢出方面的問題,當垃圾收集成為系統(tǒng)達到更高并發(fā)量的瓶頸時,我們就需要對垃圾收集技術進行監(jiān)控和調(diào)節(jié)。
1. 堆的劃分
HotSpot虛擬機將堆空間劃分為Eden區(qū),兩個Survivor空間,老年代。
對象在堆的生存流程:對象首先在Eden區(qū)中分配,當Eden區(qū)空間不足時,虛擬機會發(fā)起第一次Minor GC(指在新生代發(fā)生的垃圾收集動作),將Eden區(qū)仍然存活的對象移動到Survivor-0空間,并設置存活對象年齡設定為1,同時清理Eden區(qū),新進對象則繼續(xù)分配到Eden區(qū),直至Eden區(qū)再次空間不足,虛擬機則發(fā)起第二次Minor GC,將Eden區(qū)與Survivor-0區(qū)仍然存活的對象移動到Survivor-1空間,并設置存活對象年齡設定為2,同時將Eden與Survivor-0空間清空。對象在Survivor區(qū)中每經(jīng)過一次Minor GC,年齡就增加1歲,當年齡增加到一定歲數(shù),比如默認15歲,就會被移動到老年代中。而當老年代空間不足時,虛擬機會發(fā)起一次Major GC/Full GC,此次GC會清理老年代死亡的對象。
GC分為兩步,第一步是根據(jù)算法判斷對象是否還存活,第二步根據(jù)算法對可回收的內(nèi)存區(qū)域進行清理,下面是對這兩種算法的介紹。
2. 判斷對象是否存活的算法介紹
2.1 引用計數(shù)算法
算法原理:給對象添加一個引用計數(shù)器,如果有一個地方引用它,計算器值就加1,當引用失效,則計數(shù)器值減1。當計數(shù)器值為0時,對象就是不可能再被使用的。
例如String str = new String("");,此時堆中空字符串對象實例的計數(shù)器值為1,如果后面將str = new String("a"),此時str的引用指向了a,原來空字符串對象的計數(shù)器值便減1為0了
算法缺陷:引用計數(shù)算法沒辦法解決相互循環(huán)引用的問題,例如objA.instance = objB; objB.instance = objA; 將objA = null; objB = null,此時objA和objB都不可能被訪問了,但是objA和objB相互引用對方,兩者的計數(shù)器值都為1,沒辦法被回收,故java虛擬機沒使用該算法
2.2?可達性分析算法
算法原理:通過一系列“GC Roots”的對象作為起始點,從這些節(jié)點往下搜索,若從GC Roots到這個對象不可達,即GC Roots沒有任何引用鏈相連到該對象,則此對象是不可用的。java虛擬機使用該算法對對象存活與否進行判斷
3. 可回收的內(nèi)存區(qū)域清理的算法介紹
3.1?標記-清除算法
算法原理:最基礎的算法,分為標記和清除兩個階段,首先根據(jù)判斷對象是否存活的算法,標記出所有可回收的對象,接著將標記的對象進行統(tǒng)一回收。
算法缺陷:
一、效率問題:標記和清除兩個過程的效率不高
二、空間問題:標記清除后,會產(chǎn)生大量不連續(xù)的內(nèi)存碎片,導致后續(xù)如需分配大對象時,無法找到足夠的連續(xù)內(nèi)存
3.2?復制算法
算法原理:將內(nèi)存分為同等大小的兩塊,每次只使用一塊,當這塊內(nèi)存用完時,將存活的對象復制到另外一塊上面,再把原來這塊的內(nèi)存空間一次清理掉。這樣內(nèi)存分配時就不用考慮內(nèi)存碎片等復雜問題。
算法缺陷:算法將內(nèi)存縮小為原來的一般,代價太高了。
3.3?標記-整理算法
算法原理:標記過程與“標記-清除”算法一樣,后續(xù)步驟不是直接對可回收對象進行清理,而是讓所有存活的對象都向一端移動,然后直接清理掉端邊界以外的內(nèi)存
算法缺陷:同樣存在效率問題
3.4 分代收集算法
該算法是當前商業(yè)虛擬機都采用的垃圾收集算法
算法原理:根據(jù)對象存活周期的不同將內(nèi)存劃分為幾塊,如Java堆分為新生代和老年代。根據(jù)各個年代的特點采用適用的手機算法,在新生代,因為每次垃圾收集都會有大批對象死去,故選用復制算法,只需要付出少量存活對象的復制成本就可以完成收集。老年代則因為對象存活率高,則使用“標記-清理”或者“標記-整理”算法來進行回收。
4. 垃圾收集器
如果說收集算法是內(nèi)存回收的方法論,那么垃圾收集器就是內(nèi)存回收的具體實現(xiàn)。下面是對HotSpot包含的所有收集器進行講解。
4.1?Serial收集器
特點:單線程收集器,只會使用一個CPU或一條收集線程去完成垃圾收集,且進行垃圾收集時,須暫停其他所有的工作線程,直到收集結束。使用“復制”算法
使用場景:Client模式下的默認新生代收集器。該收集器簡單而高效,對于限定單個CPU的環(huán)境,該收集器沒有線程交互的開銷,可以做到最高的單線程收集效率。且桌面應用分配的內(nèi)存一般不大,停頓時間可控制在一百毫秒以內(nèi),故其是Client模式下一個很好的選擇。
4.2 ParNew收集器
特點:Serial收集器的多線程版本
使用場景:許多Server模式下的虛擬機中首選的新生代收集器。原因是除了Serial收集器外,只有它能與老年代的CMS收集器配合工作。故老年代在使用CMS收集器時,新生代只能使用Serial與ParNew收集器,單CPU環(huán)境下Serial效果更好,隨著CPU增加,則ParNew收集器會有很高的效率。
4.3 Parallel Scavenge收集器
特點:與其他收集器的關注點是盡可能地縮短垃圾收集時用戶線程的停頓時間不同,該收集器的目標則是達到一個可控制的吞吐量,如虛擬機運行100分鐘,其中垃圾收集耗費一分鐘,則吞吐量就是99%。該收集器通過提供參數(shù)用于精確控制吞吐量。
使用場景:用于控制具體吞吐量的新生代收集器。
4.4 Serial Old收集器
特點:單線程收集器,Serial收集器的老年代版本,使用“標記-整理”算法
使用場景:一樣主要給Client模式下的虛擬機使用
4.5?Parallel Old收集器
特點:Parallel Scavenge收集器的老年代版本,使用多線程和“標記-整理”算法
使用場景:用于控制具體吞吐量的老年代收集器。
4.6 CMS收集器
特點:以獲取最短回收停頓時間為目標的收集器,基于“標記-清除”算法
使用場景:重視服務的響應速度的應用,如B/S系統(tǒng)的服務端
//TODO
4.7 G1收集器
特點:
1. 利用多cpu或多核縮短Stop-The-World停頓的時間
2. 采用不同的方式去管理整個GC堆
3.? 整體基于“標記-整理”算法,局部基于“復制”算法
4. 可預測的停頓
使用場景:未來可替換CMS收集器
//TODO
4.8 ZGC收集器
//TODO
4.9?Shenandoah GC
//TODO
5. 常見面試問題
5.1 虛擬機GC回收的過程
5.2 虛擬機如何判斷對象是否存活
5.3 HotSpot的收集器有哪些?各自的特點是什么?重點講下cms和G1,包括原理,流程,優(yōu)缺點
5.4 對象被回收時發(fā)生了什么?
總結
以上是生活随笔為你收集整理的JVM实战与原理---内存回收策略的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: JVM实战与原理---字节码执行引擎
- 下一篇: GSON详解