GC 為什麼要掛起使用者執行緒? 什麼愁什麼怨?

starkbl發表於2021-09-09

圖片描述

前言

JVM 系列文章的第一篇。敬請期待後續。

故障描述

某年某月某日 上午,線上發生故障,經過排查,發現某核心服務 Dubbo 介面超時。

圖片描述

故障根源

檢視該服務監控指標,發現該服務 FullGC 次數過於頻繁,簡直要上天了。那也難怪介面會超時了。

那麼為啥 FullGC 次數太多會造成介面超時呢?

因為 GC 停頓。 FullGC 時會產生GC停頓,也叫 stop the world。簡稱 STW ,是指在執行垃圾收集演算法時,使用者執行緒都被掛起。這也不難理解為啥 頻繁 FullGC 會引起服務超時了。

深入探究

那麼為什麼會引起頻繁FullGC 呢?

回答這個問題之前,先了解下,有哪些情況會觸發 Full GC ?

  1. 老年代記憶體空間不足時,會觸發 FullGC.
  2. 永久代/metaspace 記憶體空間不足時,也會觸發FullGC.
  3. 顯示呼叫 GC,System.gc().(會建議jvm GC,但是不一定會GC).

產生 FullGC 的基本原因就上面三種。

故障服務就是建立很多物件,無法回收,導致記憶體不足,然後 GC 回收不了時,就會引起頻繁 FullGC 了。

復現故障

根據記憶體不足建立物件會引起 FullGC 的原理,寫了一個 Demo ,觀察GC 情況。

程式碼如下:

圖片描述

程式碼很簡單,就是讓上次建立的物件可以被回收,然後繼續建立物件,然後連結到根結點,使其不會被回收。

使用啟動引數 -Xms512m -Xmx512m 設定堆記憶體大小。

啟動 Demo ,然後發起請求,觀察GC 情況。

首先,使用命令 jps -l 檢視程式ID

圖片描述

然後使用 jstat 命令檢視GC資訊 ():

圖片描述

上圖可以看到 正在不停的進行 Full GC.

圖片描述

上圖可以看出,老年代,以及後設資料區 記憶體空間已滿,這也是 不停 Full GC 的原因。

再看我發出的請求:

圖片描述

過去這麼久,依然沒有結果。

使用 jstack 命令檢視 執行緒狀態,發現 使用者執行緒已經被掛起。

圖片描述

不難看出,頻繁的 FullGC 已經影響到了應用的正常執行。

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/3705/viewspace-2824751/,如需轉載,請註明出處,否則將追究法律責任。

相關文章