GC
GC 全稱為garbage collection,中文含義為垃圾回收,在jvm中的含義為回收無用內存空間
Young space
中文名為年輕代或者新生代,為JVM 堆的一部分,由分代GC概念劃分而來,保存生命周期較短的對象
Tenured space
中文名為老年代或年老代,為JVM 堆的一部分,由分代GC概念劃分而來,保存生命周期較長的對象
Minor GC
minor gc指的是發生在年輕代或者說新生代(Young space)中的gc,也有人稱其為young gc或者ygc,在下文中我們統一使用minor gc表示
Major GC
major gc指的是發生在老年代(Tenured space)中的gc,也有人稱為old gc,o gc,cms gc等,在下文我們統一使用major gc表示
stop the world
指的是用戶線程在運行至安全點(safe point)或安全區域(safe region)之后,就自行掛起,進入暫停狀態,對外的表現看起來就像是全世界都停止運轉了一樣,而不論何種gc算法,不論是minor gc還是major gc都會stop the world,區別只在于stop the world的時間長短。
什么是Full GC
先說一下結論,Full GC這個概念是沒有官方定義的,而且含義還特別混亂,在不同地方表達的含義是不同的,需要就不同的場景分別進行討論。
大眾認知上
在通常意義上人們口中說的Full GC為一次特殊GC行為的描述,這次GC會回收整個堆的內存,包含老年代,新生代,metaspace等,這個是最常見的一種認知,很多人也就了解到這個程度,因此在遇到一些特殊場景的時候就會發現實際情況和自己的認知會發生沖突
從GC日志上
在gc.log中會發現在部分gc日志頭中也有Full GC這樣的字眼,這里表示的含義是在這次GC的全過程中,都是Stop The world的狀態,也就是說在這次GC的全過程中所有用戶線程都是處于暫停的狀態,那么在這里要噴一下中文jvm神書《深入理解JVM》了,在第二版第89頁有這么一段話:
GC 日志開頭的“[GC”和“[Full GC”說明了這次垃圾收集的停頓類型,而不是用來區分新生代GC還是老年代GC的。如果有“Full”,說明這次GC是發生了Stop-The-World的,例如下面這段新生代收集器ParNew的日志也會出現“[Full GC”(這一般是因為出現了分配 擔保失敗之類的問題 .所以才導致STW)。如果是調用System.gc()方法所觸發的收集,那么在這里將顯示“[Full GC (System)”。
這段話的描述是錯誤的,因為在前面說過,不論何種gc算法,不論新生代或是老年代,其gc都會發生stop the world,這里正確的描述是這次GC的全過程都是Stop-The-World的
從JDK自帶的工具上
使用jstat -gc命令能夠查看到制定java 線程的gc次數,那么在經過我的多次嘗試以及對比之后,我發現了使用jstat 查出來的FGC 次數和時間,實際上指的是老年代的收集器發生Stop the world 的次數和持續時間,對應本文而言,就是CMS收集器的Stop the world次數和時間
其他含義(坑爹版)
前面不是說到我在監控大盤上看到這個應用平均一分鐘發生了十多次”Full GC”么,在我弄明白了前面兩個Full GC的含義之后查看了gc.log文件,隨后發現該應用實際上一次Full GC都沒有出現,然后咨詢了一下提供監控數據的同學,結果他說是通過JMX獲取的,代碼為:
ManagementFactory.getGarbageCollectorMXBeans()
然后眾所周知,使用MXBean獲取到的只是收集器的執行次數,和Full GC半毛錢關系都沒有啊,隨后在追問了一下,發現做監控系統的同學直接把CMS收集器的收集次數當做了Full GC的次數來統計,what the fuck????,只能說對于FUll GC的概念真的有很多人是一直沒弄懂過的
結束語
在這篇文章快寫完的時候,用google隨便搜了一下就在首頁找到一篇對于各類gc概念介紹得比較透徹的文章,和使用度娘一搜首頁全是各種抄來抄去的錯誤文章相比,對比簡直是太強烈了,由此得出結論,技術類的資料能在外網查就在外網查吧,省時又省力,最后附上我找到的這篇文章貌似還是plumbr的聯合創始人寫的,不得不說很給力了