JVM(3)-垃圾收集器與記憶體分配策略

Zouxxyy發表於2019-03-23

如何判斷物件為垃圾物件

引用計數法

給物件新增一個引用計數器,每當有個物件引用它時,計數器加1;引用失效時計數器減1;為0時物件不可能被再引用。

沒有使用的原因:很難解決物件之間相互迴圈引用的問題

可達性分析演算法

看作為GC Roots的物件作為起始點,和它連通的是可用的,反之不可用

如下情況的物件可以作為GC Roots:

  • 虛擬機器棧(棧楨中的本地變數表)、本地方法棧中JNI(Native方法)中的引用的物件
  • 方法區中的類靜態屬性引用的物件
  • 方法區中的常量引用的物件

當物件不可達時,可以執行fianlize(),但該方法自會被自動呼叫一次,有點像c++的解構函式,書上說最好別用。

引用的分類

  • 強引用:Objece obj = new Object(),永遠不會被垃圾蒐集回收
  • 軟引用:SoftReference類實現,可以存活第一次回收,但第二次就GG
  • 弱引用:WeakReference類實現,第一次就GG
  • 虛引用:PhantomReference類實現,不能通過它取得例項,唯一作用就是當該物件被回收時會收到一個系統通知。

如何回收

垃圾收集演算法

  • 標記-清除演算法:(老年代)先標記,再清除。缺點:效率低,記憶體碎片化
  • 複製演算法:(新生代)HotSpot虛擬機器把記憶體分為Eden和2塊Survivor區,把在Eden和Survivor中 存活的物件 複製到空閒的一塊Survivor中。不夠時可以向老年代擔保。
  • 標記-整理演算法:(老年代)標記 -> 移動到一起 -> 清理
  • 分代收集演算法:把記憶體分為新生代和老年代。根據年代選則合適的演算法。

垃圾收集器

新生代 老年代 特殊
Serial(單執行緒) Serial Old(單執行緒,CMS備胎) G1(Region優先順序回收)
ParNew(多執行緒) CMS(併發)
Parallel Scavenge(關注吞吐量)
  • 並行(Parallel):多條垃圾收集執行緒並行工作,但此時使用者執行緒仍處於等待狀態。
  • 併發(Concurrent):使用者執行緒與垃圾收集執行緒同時執行。

如何分配

以HosSpot收集器的分配和回收策略為例

  • 優先分配在Eden
  • 大物件直接進入老年代
  • 長期存活的物件進入老年代
  • 動態物件年齡判定
  • 空間分配擔保

相關文章