【深入理解Java虛擬機】垃圾回收

引用計數演算法

給對象加一個計數器,引用一次+1,引用時效就-1,當計數器=0時對象就不能再被使用;
實現簡單,判定效率高;Java虛擬接沒有使用,主要原因是很難解決對象之間循環引用問題;

GC演算法:

GC Roots 作為起始點,開始向下搜索,這個搜索路徑叫做引用鏈,當一個對象到GC Roots沒有任何引用鏈,那麼這個對象就是不可用的。
Java中可作為GC Roots的對象:虛擬機棧中的引用對象、方法區中類靜態屬性引用對象、方法區中常量引用對象等。

標記清除演算法

分為標記和清除階段,首先標記所有需要回收的對象,在標記完後統一回收標記的對象。
堆中的老年代:因為存活率高,沒有額外空間進行分配擔保,就必須使用標記清理演算法回收。
標記清理演算法問題:

  • 1、標記和清除的效率不高;
  • 2、標記清除後會產生大量不連續的記憶體碎片,當需要分配較大對象時無法找到足夠記憶體,又會觸發垃圾收集動作;

複製演算法

堆中的新生代:每次垃圾回收都有大量對象死去,只有少量存活所以使用複製演算法;
jvm的複製演算法是將記憶體劃分為一塊較大空間Eden和兩塊較小的Suvivor,一般比例是8:1:1。每次只是用Eden和Suvivor中的一塊,當回收時,將Eden和Suvivor中存活的對象複製到另一塊Suvivor中,再將Eden和使用的Suvivor清除掉。

標記壓縮演算法(標記整理)

標記-壓縮演算法與標記-清理演算法類似,只是後續步驟是讓所有存活的對象移動到一端,然後直接清除掉端邊界以外的記憶體

垃圾收集器

常見的垃圾收集器:

Serial:新生代收集器,單執行緒。
ParNew:新生代收集器,Serial的多執行緒版本,和CMS配合工作。
Parallel Scavenge:新生代,可以控制吞吐量。配合自適應調節策略,可以讓虛擬機自動完成記憶體調優。
Serial Old:Serial老年代版本,單執行緒。
Parallel Old:Parallel Scavenge老年代版本,多執行緒
CMS:老年代收集器,特點:並發,低停頓,以獲取最短回收停頓時間為目標。基於標記-清除演算法。
CMS過程

  • 1初始標記 :標記GC Roots能直接關聯的對象,速度很快。
  • 2並發標記 :進行GC Roots Tracing的過程,耗時長
  • 3 重新標記 :修正並發標記期間不正確的標記記錄
  • 4 並發清除

Minor GC和Full GC之間的區別

堆記憶體劃分為 Eden、和兩塊Survivor,JDK1.8移除了永久代。

  • Minor GC 新生代GC: JAVA對象大多具備朝生夕滅的特性,所以Minor GC非常頻繁,回收速度也比較快。
  • Full GC/Major GC 老年代GC: 速度一般比Minor GC慢很多。

記憶體分配策略

  • 對象優先在新生代Eden區中分配,當Eden區沒有足夠空間時,虛擬機發起Minor GC.
  • 大對象直接進入老年代,大對象典型的就是很長的字元串或數組。
  • 長期存活的對象進入老年代。