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