垃圾回收基礎理論

垃圾

沒有任何引用指向的對象都是垃圾

找垃圾的方法

  • 引用計數法:一個對象創建時會分配一個計數器,有引用指向這個對象時,計數器+1,當引用失效,計數器-1,當計數器爲0時,就可以判斷爲一個垃圾對象(這種方法解決不了循環引用的問題)
  • 根可達算法:以GC Roots爲根展開引用鏈路搜索,如果一個對象沒有任何鏈路跟GC Roots關聯,那麼就可以判斷爲一個垃圾對象
    • GC Roots的對象:線程棧變量,靜態變量,常量池,JNI指針(本地方法對象)

垃圾清除的算法

  • 標記清除算法:
    • 優點:標記處垃圾對象後清除,算法相對簡單,存活對象多的情況效率較高
    • 缺點:兩邊掃描(找出有用對象,找出垃圾對象並清理)效率偏低,容易產生碎片。
  • 拷貝算法:
    • 優點:適用於對象較少的情況,只掃描一次,效率提高沒有碎片
    • 缺點:空間浪費,移動複製對象需要調整對象引用
  • 標記壓縮算法:
    • 優點:不會產生碎片,方便對象分配,不會內存減半
    • 缺點:掃描兩次,需要移動對象,效率偏低。

堆區內存分步圖

在這裏插入圖片描述

進入老年代年齡的參數

-XX:MaxTenuringThreshold

棧上分配

  • 線程私有小對象
  • 無逃逸(沒有被外層引用)
  • 支持標量替換(使用普通類型代替對象)
  • 無需調整(不需要GC優化)

線程本地分配 TLAB(Thread Local Allocation Buffer)

  • 佔用eden,默認1%
  • 多線程的時候,不用競爭,eden就可以申請空間,提高效率
  • 小對象
  • 無需調整

對象何時進入老年代

超過tenuringThreShould 指定次數(YGC)

  • Parallel Scavenge:15
  • CMS:6
  • G1:15

動態年齡

Eden和S1在GC中存活的對象,超過了S2容量的50%,年齡大的直接放入老年代

分配擔保

YGC期間,有對象進來,survivor區的空間不夠了,空間擔保直接進入老年代

對象創建內存分步流程圖

對象內存分配流程圖

常見的垃圾回收器

Jdk誕生Serial追隨,提高效率誕生了PS,爲了配合CMS產生了ParNew,1.4後期誕生了CMS,CMS是里程碑式的GC,它開啓了併發回收的過程,但是CMS毛病較多,因此目前任何一個JDK版本默認是CMS 併發垃圾回收是因爲無法忍受STW

常見的垃圾回收器

  • Serial:年輕代串行回收
  • Serial Old:單線程在老年代
  • PS:年輕代,並行回收
  • ParNew:年輕代配合CMS的並行回收
  • CMS:
    • 初始標誌:標記根對象
    • 併發標記:佔失敗80%,一遍產生垃圾,一邊標記
    • 重新標記:STW
    • 併發清理:會產生浮動垃圾

缺點:內存碎片化,浮動垃圾 解決方案:降低觸發CMS閾值-XX:CMSinitiation Occupancy Fraction92%減少到65%甚至更低,保證老年代有足夠的空間。

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