關於JVM的垃圾回收

天启A發表於2024-11-05

垃圾回收主要回收的是堆中的例項、陣列。

STW(stop the world)暫停所有應用程式的執行緒,等待垃圾回收完成

1.物件什麼時候可以被垃圾回收器回收

一個物件如果沒有任何的引用指向他了,那麼他現在就是不可達物件(垃圾),如果定位了垃圾,那麼垃圾回收器就可能會將他回收。(比如這個物件被顯式的設定為null,可以讓垃圾回收器更好的識別他並回收)

定位垃圾有兩種辦法:

  • 引用計數法(不常用,迴圈引用會導致記憶體洩漏問題),
  • 可達性分析演算法(常用,掃描堆內的物件,如果沿著GC root物件為起點的引用鏈找不到該物件,則表示該物件可以回收)
    • 可達性分析法有哪些可以作為GC root的物件
      • 虛擬機器棧幀中的物件
      • metaspace中類靜態屬性引用的物件、常量引用的物件
      • native修飾的方法

2.JVM中的垃圾回收演算法都有哪些

標記清除演算法

  • 標記:根據可達性演算法將得出的垃圾進行標記
  • 清除:對這些標記為可回收的物件進行垃圾回收
  • 清除和回收速度相對較快,但是會導致記憶體不完整,碎片化比較嚴重

標記整理演算法(老年代常用演算法)

  • 在標記清除演算法的基礎上,再將物件位置進行移動,雖然解決了碎片化問題,但是在效能上會有一定影響

複製演算法(年輕代常用演算法)

需要開闢兩個大小完全相同的記憶體空間;

同樣是透過gc root標誌垃圾;在垃圾回收後,會將存活的物件複製到另一個區域,該區域全部清空。

在垃圾物件較多的情況下效率較高,而且無碎片化;但是需要分配兩塊記憶體空間,並且有一塊在同一時間內是無法使用的

3.JVM中的分代回收

堆會進行區域劃分:新生代(eden,倖存者區to,倖存者區from):老年代比例為1:2

物件分代回收策略:

  1. 新建立的物件都先分配到eden區;
  2. eden區記憶體不足時,會標記eden區與from區的存活物件
  3. 採用複製演算法將存活物件複製到to中,複製完畢後釋放eden和from區記憶體
  4. eden區記憶體再次不足時,標記eden區和to區存活物件,再次進行復制演算法將其移動到from區,回到2
  5. 當倖存區物件經歷多次回收(至多15次),會從新生代晉升為老年代。(倖存區記憶體不足或者大物件也會提前晉升)

4.MinorGC、MixedGC、fullGC的區別是什麼

MinorGC(youngGC)發生在新生代的垃圾回收,暫停時間短(STW)

MixedGC發生在新生代+老年代部分割槽域的垃圾回收,由G1收集器持有

fullGC新生代+老年代完整的垃圾回收,STW時間很長,應極力避免

5.JVM都有哪些垃圾回收器

序列垃圾回收器:分為serial和serial old序列垃圾收集器,使用單執行緒進行垃圾回收,堆記憶體較小,適合個人電腦

  • serial作用於新生代,使用複製演算法;serial old作用於老年代,使用標記-整理演算法。垃圾回收時,只有一個執行緒在工作,其他執行緒都要STW,等待垃圾回收完成

並行垃圾回收器:分為parallel new和parallel old,JDK8預設使用該回收器

  • parallel new作用於新生代,使用複製演算法;parallel old作用於老年代,使用標記-整理演算法。與序列不同的是,並行回收是多個執行緒在工作,其他沒什麼不同....

CMS(併發)垃圾回收器concurrent mark sweep:主要針對老年代的垃圾回收器。停頓時間短,使用者體驗好;在進行垃圾回收時應用可以正常執行。有以下四個工作階段

  • 初始標記:短暫的STW,標記一下GCroot關聯的物件
  • 併發標記:標記出所有科可達物件
  • 重新標記:修正併發標記期間的變動,需要STW
  • 併發清楚:採用標記-清除法,會有記憶體碎片

G1垃圾回收器

G1和其他垃圾回收器的區別就是不再按預設的將堆分為新生代與老年代,而是將堆劃分為多個大小相同的region,每一個region可以按需要來充當eden、survivor、old。也因此G1可以預測STW

JDK9之後預設垃圾回收器都是採用的G1。G1應用於老年代與新生代

劃分了多個區域,每個區域都可以作為eden,survivor,old,humongous(專門儲存大物件,如果一個儲存空間不夠的話他是會連續儲存來實現humongous);採用複製演算法。

如果垃圾回收速度趕不上新建物件速度會導致fullGC

有三個工作階段:

  1. 年輕代垃圾回收
    1. 初始時,所有區域都處於空閒狀態
    2. 剛剛建立物件時,會隨機選擇一些空間作為eden區
    3. 當eden區需要進行垃圾回收時,挑選一個空閒區作為survivor區,用複製演算法複製存活物件,需暫停使用者執行緒(這裡的STW很短)
    4. eden區會和新的survivor透過複製演算法合併成新的survivor區,其中較老的物件晉升至老年代
  2. 併發標記
    1. 當老年代佔用記憶體超過閾值(預設45%)後,觸發併發標記,無STW
  3. 混合垃圾回收
    1. 回收存活物件較少的老年代,和survivor區中的合併為新的old

6.強引用,軟引用,弱引用,虛引用的區別

強引用:只有所有的GCroot都不透過強引用引用該物件,該物件才能被垃圾回收

軟引用:SoftReference當觸發一次垃圾回收時,下一次垃圾回收就會回收該物件

弱引用:WeakReference垃圾回收時,無論記憶體是否充足都會回收弱引用物件。ThreadLocal記憶體洩漏問題就是因為Entry extend WeakReference

虛引用:需配合引用佇列使用,被引用物件回收時,會將虛引用入隊,由Reference Handler執行緒呼叫相關方法釋放記憶體。該引用主要用於跟蹤物件被垃圾回收的狀態

相關文章