java垃圾回收-讀書筆記《深刻理解java虛擬機》
GC須要完成的3件事情
判斷對象已死方法(哪些內存須要回收)
- 引有計數法
- 給對象添加一個引用計數器
- 每當有一個地方引用它時,計數加1
- 當引用失效時,計數減1
- 計數器爲0的對象就是不可能再被使用的
- 問題:很難解決對象循環引用
- 可達性分析法
- Java中使用方法
- 基本思路:沒有被GC Roots對象引用鏈引用到的對象
- Java中,可做爲GC Roots的對象有:
- 虛擬機棧中引用的對象
- 方法區中類靜態屬性引用的對象
- 方法區中常量引用的對象
- 本地方法棧中JNI引用的對象
垃圾回收算法(如何回收)
- 標記-清除算法(Mark-Sweep)
- 思路:
- 首先標記出全部須要回收的對象
- 在標記完成後統一回收全部被標記的對象
- 不足:
- 效率問題,標記和清除兩個過程效率都不高
- 空間碎片太多,分配較大對象時,沒有足夠大的連續空間,不得不提早觸發另外一次垃圾回收動做
- 複製算法
- 思路:
- 將可用內存按容量劃分爲大小相等的兩塊
- 每次只使用其中一塊
- 當這一塊的內存用完了,就將還存活着的對象複製到另一塊上面
- 而後再把已使用過的內存空間一次清理掉
- 優勢:
- 實現簡單,運行高效
- 每次都是對整個半區進行內存回收
- 內存配時不用考慮內存碎片等複雜狀況,只要移動堆頂指針,按順序分配便可
- 不足:
- 通常用來回收新生代
- 將內存分爲一塊較大的Eden空間、兩塊較小的Survivor空間
- 每次使用Eden和其中一塊Survivor
- 當回收時,將Eden和Survivor中還存活對象所有複製到另外一塊Survivor中
- 最後清理掉Eden和剛用過的Survivor空間
- HotSpot虛擬機默認Eden:Survivor爲8:1
- 當Survivor空間不夠用時,須要依賴其餘內存(老年代)進行分配擔保
- 標記-整理算法
- 思路:
- 標記過程仍然與「標記-清除」算法同樣
- 讓全部存活的對象都向一端移動
- 而後直接清理掉端邊界之外的內存
- 通常用於老年代
- 分代收集算法
- 思路:
- 通常Java堆分爲兩塊
- 新生代
- 每次垃圾收集時都發現有大批對象死去,只有少許存活
- 選用複製算法
- 老年代
- 對象存活率高
- 沒有額外空間對它進行分配擔保
- 使用「標記-清理」或「標記-整理」進行回收
HotSpot的算法實現
垃圾收集器
內存分配與回收策略
- 對象優先在Eden分配
- 大對象直接進入老年代
- 長期存活的對象將進入老年代
- 動態對象年齡斷定
- 空間分配擔保
掃一掃 關注個人公衆號
【老羅開發】
歡迎關注本站公眾號,獲取更多信息