談到JVM,你們都知道GC(Garbage Collection),GC這個話題說淺了就一句話--JVM自動垃圾收集,說深了就無止盡了,回收算法,各類收集器,gc類型,gc觸發點....等等,做者也是略懂皮毛,這裏給你們推薦一個知乎上比較活躍的JVM大牛,RednaxelaFX,是專門作JVM開發的,業界號稱"R大"。放個傳送門:R大
鑑於做者才學疏淺,這篇博文仍是準備用通熟易懂的話把做者本身對GC這一塊的理解作陳述,概要以下:html
文章結構算法
- 哪些內存須要回收(Which)
- 各類GC的觸發時機(When)
- 如何回收(How)
3.1 回收算法
3.2 HotSpot的具體實現-各類收集器- GC日誌
大多數沒幹過C或者C++的Javaer是幸福的,由於沒有體會過那種本身new delete內存的感受,建立對象就是new,無論內存的回收問題。其實咱們的內存是JVM的GC機制來幫咱們回收的。那麼問題來了。到底哪些內存須要回收呢?
答案:可達性分析算法,說白了,就是JVM預先肯定一組GC roots引用變量,如Student stu =new Student();這個stu就能夠做爲GC roots,當進行垃圾回收時,JVM經過GC Roots找到可以引用到的全部活對象,而後把剩下的對象標記爲"無用",即可回收狀態!
可以做爲GC roots的引用以下:服務器
說到GC類型,就更有意思了,爲何呢,由於業界沒有統一的嚴格意義上的界限,也沒有嚴格意義上的GC類型,都是左邊一個教授一套名字,右邊一個做者一套名字。爲何會有這個狀況呢,由於GC類型是和收集器有關的,不一樣的收集器會有本身獨特的一些收集類型。因此做者在這裏引用R大關於GC類型的介紹,做者以爲仍是比較穩當準確的。以下:數據結構
上面你們也看到了,GC類型分分類是和收集器有關的,那麼固然了,對於不一樣的收集器,GC觸發時機也是不同的,做者就針對默認的serial GC來講:線程
因爲網上已經擁有很是多的優秀博文來詳細介紹關於回收算法這塊,因此這塊做者將引用其餘博客的介紹並加上本身的一些描述:
3.1.1 標記清除算法(Mark-Sweep)
日誌
複製算法在JVM新生代垃圾回收中的運用:
cdn
Eden:From:TO =8:1:1
因爲新生代中90%的對象都是"朝生夕死",採用複製算法是比較合理的,首先只移動了存活下來的對象(比較少數),其次,內存在移動到To區域後是有順序的,不存在內存碎片。
值得一提的是,假如在一次MinorGC時,Eden中存活的對象+From中存活的對象>To的剩餘空間,則會經過擔保機制將對象直接轉移到Old gen ,若是Old gen的內存空間也不夠,則進行一次Full gc .
當對象的年齡到達15歲時會轉移到Old gen (可經過參數配置,通常不建議更改。)htm
3.1.3標記-整理算法(Mark-Compact):
對象
因爲Old gen 的大部分對象都是年齡很大的對象,因此存活率比較高,採用複製算法確定是行不通的(較多的對象複製操做),因此才大部分收集器的old gen採用 Mark-Compact算法,避免了空間碎片。blog
3.1.4三種算法比較:
稍微解釋一下常見的關於GC時間的問題:
爲何FGC的時間比MinorGC長不少?
答:FGC進行了old gen的gc,因爲算法上採用Mark-Sweep或者Mark-Compact,進行了不少對象(老年代存活率很低)的移動,固然很耗時了!其實就是空間換時間,時間換空間的問題。
關於收集器這塊,因爲本人也是JVM初學者,加上不多有在生產環境作收集器參數調整,搭配使用的機會。因此能夠說對於一些HotSpot收集器只是停留在
書籍與博文層次,因此這裏就不賣弄了。下面給一個傳送門你們自行看一看吧:
www.jianshu.com/p/50d5c88b2…
-XX:+PrintGCDateStamps
-XX:+PrintGCDetails
-Xloggc:/Users/zdy/Desktop/dump/gclog.txt
當服務器出現卡頓比較頻繁時,嘗試看下本身的GC日誌,注意Full gc 頻率。
最後,稍微說一下做者的心得: