1、CMS及其執行過程?
CMS,全稱Concurrent Mark and Sweep,用於對年老代進行回收,目標是儘量減少應用的暫停時間,減少full gc發生的機率,利用和應用程序線程併發的垃圾回收線程來標記清除年老代。CMS並非沒有暫停,而是用兩次短暫停來替代串行標記整理算法的長暫停。
內外的設置正常收集週期是這樣的:
1)CMS-initial-mark 初始標記
2)CMS-concurrent-mark 併發標記的
3)CMS-concurrent-preclean 執行預清理 注: 相當於兩次 concurrent-mark. 因爲上一次c mark,太長.會有很多 changed object 出現.先幹掉這波.到最好的 stop the world 的 remark 階段,changed object 會少很多.
4)CMS-concurrent-abortable-preclean 執行可中止預清理
5)CMS-remark 重新標記
6)CMS-concurrent-sweep 併發清除
7)CMS-concurrent-reset 併發重設狀態等待下次CMS的觸發其中,CMS-initial-mark和CMS-remark會stop-the-world。
2、爲什麼 CMS兩次標記時要 stop the world?
我們知道垃圾回收首先是要經過標記的。對象被標記後就會根據不同的區域採用不同的收集方法。看上去很完美的一件事情,其實並不然。
大家有沒有想過一件事情,當虛擬機完成兩次標記後,便確認了可以回收的對象。但是,垃圾回收並不會阻塞我們程序的線程,他是與當前程序併發執行的。所以問題就出在這裏,當GC線程標記好了一個對象的時候,此時我們程序的線程又將該對象重新加入了“關係網”中,當執行二次標記的時候,該對象也沒有重寫finalize()方法,因此回收的時候就會回收這個不該回收的對象。
虛擬機的解決方法就是在一些特定指令位置設置一些“安全點”,當程序運行到這些“安全點”的時候就會暫停所有當前運行的線程(Stop The World 所以叫STW),暫停後再找到“GC Roots”進行關係的組建,進而執行標記和清除。
這些特定的指令位置主要在:
- 1、循環的末尾
- 2、方法臨返回前 / 調用方法的call指令後
- 3、可能拋異常的位置
感謝兩位大佬的總結:https://blog.csdn.net/fei33423/article/details/70941939