天天看點

Java堆與垃圾收集器(GC)

Java堆:

Java堆記憶體空間在虛拟機啟動時建立,是Java虛拟機鎖管理的最大記憶體區域;垃圾收集器的主要區域;它被所有線程共享。堆記憶體的唯一目的是存放對象執行個體。

Java堆空間分為老年代和新生代。老年代用于存儲經過多次Minor GC後,任然存活的對象,或者是建立的大對象(新生代空間不足,會直接将大對象存放在老年代);新生代主要用于存儲新建立的對象,新生代又分為Eden區、From Survivor區(也叫From區)、To Survivor區(也叫To區)。如下圖:

Java堆與垃圾收集器(GC)

新建立的對象存儲在新生代中的Eden區,eden區也是新生代的主要記憶體區;Eden區的對象經過一次GC後依然存活的對象會進入from區,from區經過一次GC後将存活的對象存入to區,to區經過一次GC後會将存活的對象存入from區。這裡from區和to區不是固定的,而是會随着GC算法互相轉化,from區可以為to區,to區可以為from區。嚴格的來說,都是from區經過一次GC後,将存活的對象存入to區。而from區和to區的對象經過若幹次GC後(預設15次),如果依然存活,則會進入到老年代。而判斷一個類是否死亡,需同時滿足三個條件:

  •           (1)、該類所有的執行個體都已經被回收,也就是Java堆中不存在該類的任何執行個體;
  •           (2)、加載該類的ClassLoader已經被回收
  •           (3)、該類對應的java.lang.Class對象沒有在任何地方被引用,無法在任何地方通過反射通路該類的方法。

GC:

  • Minor GC:新生代GC,指發生在新生代的垃圾收集動作,所有的Minor GC都會觸發全世界的暫停(stop-the-world),停止應用程式的線程,不過這個過程非常短暫。當堆中的Eden區空間不足時會出發monor GC
  • Major GC/Full GC:老年代GC,指發生在老年代的GC。老年代中空間不足時觸發Major/Full GC

垃圾收集器:

  • 新生代:serial收集器、parNew收集器、parallelScavenage收集器
  • 老年代:CMS收集器、serialOld收集器、parallelOld收集器
  • 通用收集器:G1收集器,可用于新生代,也可用于老年代
Java堆與垃圾收集器(GC)

實作連接配接的收集器,表示可以設定新生代和老年代的垃圾收集器配合使用。

  • serial收集器:是Hotspot運作在Client模式下的預設新生代收集器,使用停止指派算法。它是單線程、串行垃圾收集器,在進行垃圾收集工作時會暫停其他線程。可以使用 -XX:+UseSerialGC開啟。特點是簡單高效,在管理記憶體空間不大的情況下适合使用。
  • parNew收集器:是Serial的多線程版本,用多個線程進行GC,并行,其它工作線程暫停,關注縮短垃圾收集時間。除使用多線程GC外,其他參數、算法、規則與Serial完全相同。使用-XX:+UseParNewGC開啟ParNew+Serial Old收集器組合收集記憶體;使用-XX:ParallelGCThreads來設定執行記憶體回收的線程數。
  • Parallel Scavenge 收集器:使用停止複制算法,關注CPU吞吐量。系統吞吐量=運作使用者代碼時間 / (運作使用者代碼時間+垃圾收集時間)。使用-XX:+UseParallelGC開啟Parallel Scavenge+Serial Old收集器組合回收垃圾(這是在Server模式下的預設值);使用-XX:GCTimeRatio來設定使用者執行時間占總時間的比例,預設99,即1%的時間用來進行垃圾回收。使用-XX:MaxGCPauseMillis設定GC的最大停頓時間(隻對Parallel Scavenge有效);-XX:+UseAdaptiveSizePolicy可以進行動态控制,如自動調整Eden/Survivor比例,老年代對象年齡,新生代大小等,這個參數在ParNew下沒有。
  • CMS(Concurrent Mark Sweep)收集器:是以擷取最短垃圾收集停頓時間為目标的收集器,CMS收集器的關注點盡可能縮短垃圾收集時使用者線程的停頓時間,停頓時間越短就越适合與使用者互動的程式。使用标記清除算法,多線程,優點是并發收集(使用者線程可以和GC線程同時工作),停頓小。使用-XX:+UseConcMarkSweepGC開啟ParNew+CMS+Serial Old進行記憶體回收,優先使用ParNew+CMS,當使用者線程記憶體不足時,采用備用方案Serial Old收集。
  • Serial Old收集器:單線程、串行收集器,使用标記整理(整理的方法是Sweep(清理)和Compact(壓縮))算法,使用單線程進行GC,其它工作線程暫停。
  • Parallel Old收集器:多線程,并行收集器,使用标記整理(與Serial Old不同,這裡是Summary(彙總)和Compact(壓縮),彙總指将幸存的對象複制到預先準備好的區域,而不是像Sweep(清理)那樣清理廢棄的對象)算法。在Parallel Old執行時,仍然需要暫停其它線程。Parallel Old出現後,與Parallel Scavenge配合有很好的效果,充分展現Parallel Scavenge收集器吞吐量優先的效果。使用-XX:+UseParallelOldGC開關控制使用Parallel Scavenge +Parallel Old組合收集器進行收集。
  • G1收集器:JDK1.7出現,既可以回收新生代,也可以回收老年代。基于“标記—整理”算法,不會産生碎片空間,可以精确控制停頓時間。面向服務端應用的垃圾收集器,主要針對配備多核CPU及大容量記憶體的機器,以極高機率滿足GC停頓時間的同時,還兼具高吞吐量的性能特征。

JDK8中預設使用組合是: Parallel Scavenge GC 、ParallelOld GC

JDK9預設是用G1為垃圾收集器

JDK14 棄用了: Parallel Scavenge GC 、Parallel OldGC

JDK14 移除了 CMS GC

常用垃圾收集器參數: 

Java堆與垃圾收集器(GC)

GC日志參數:

Java堆與垃圾收集器(GC)