GC 相關問題

1、美團經典文章:https://tech.meituan.com/2017/12/29/jvm-optimize.html

2、參考文章:https://www.cnblogs.com/Leo_wl/p/5393300.html

3、GC 概念:https://www.jianshu.com/p/5ace2a0cafa4

4、CMS GC日誌詳細介紹:https://blog.csdn.net/bmwopwer1/article/details/71947137

5、GC root的定義:https://www.zhihu.com/question/53613423/answer/135743258

併發標記和重新標記兩個階段中間還增加了兩個階段: [CMS-concurrent-preclean-start] 併發預清理階段和 [CMS-concurrent-abortable-preclean-start] 併發可中斷預清理階段。這兩個階段都是爲了減輕後續進行的重新標記階段的工作量。併發預清理階段主要處理在併發標記階段重新進入老年代的對象。併發可中斷預清理階段等待Minor GC的執行。

重新標記階段由於跨代引用的存在,需要對整個堆進行掃描。但是重新標記階段是STW的,爲了縮短重新標記階段的時間,需要儘量減少Eden區的大小。有兩種方式:增加可中斷的併發預清理階段,默認最大等待5s,如果中間發生Minor GC是理想的結果。通過可配置的參數保證Remark前強制進行一次Minor GC。

跨代引用在Minor階段也是存在的,因此也要解決類似問題。Minor是通過卡表實現的,因爲老年代引用新生代對象的比例非常低,根據這一特性JVM引入了卡表(card table)來實現這一目的。卡表的具體策略是將老年代的空間分成大小爲512B的若干張卡(card)。卡表本身是單字節數組,數組中的每個元素對應着一張卡,當發生老年代引用新生代時,虛擬機將該卡對應的卡表元素設置爲適當的值。如上圖所示,卡表3被標記爲髒(卡表還有另外的作用,標識併發標記階段哪些塊被修改過),之後Minor GC時通過掃描卡表就可以很快的識別哪些卡中存在老年代指向新生代的引用。這樣虛擬機通過空間換時間的方式,避免了全堆掃描。

 

哪些是GC root:

  • 所有Java線程當前活躍的棧幀裏指向GC堆裏的對象的引用;換句話說,當前所有正在被調用的方法的引用類型的參數/局部變量/臨時值。
  • VM的一些靜態數據結構裏指向GC堆裏的對象的引用,例如說HotSpot VM裏的Universe裏有很多這樣的引用。
  • JNI handles,包括global handles和local handles
  • (看情況)所有當前被加載的Java類
  • (看情況)Java類的引用類型靜態變量
  • (看情況)Java類的運行時常量池裏的引用類型常量(String或Class類型)
  • (看情況)String常量池(StringTable)裏的引用

注意,是一組必須活躍的引用,不是對象

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章