GC 爲何要掛起用戶線程? 什麼愁什麼怨?

GC 爲何要掛起用戶線程? 什麼愁什麼怨?

img

前言

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

故障描述

某年某月某日 上午,線上發生故障,通過排查,發現某核心服務 Dubbo 接口超時。git

img

故障根源

查看該服務監控指標,發現該服務 FullGC 次數過於頻繁,簡直要上天了。那也難怪接口會超時了。github

那麼爲啥 FullGC 次數太多會形成接口超時呢?算法

由於 GC 停頓。 FullGC 時會產生GC停頓,也叫 stop the world。簡稱 STW ,是指在執行垃圾收集算法時,用戶線程都被掛起。這也不難理解爲啥 頻繁 FullGC 會引發服務超時了。jvm

深刻探究

那麼爲何會引發頻繁FullGC 呢?spa

回答這個問題以前,先了解下,有哪些狀況會觸發 Full GC ?.net

  1. 老年代內存空間不足時,會觸發 FullGC.
  2. 永久代/metaspace 內存空間不足時,也會觸發FullGC.
  3. 顯示調用 GC,System.gc().(會建議jvm GC,可是不必定會GC).

產生 FullGC 的基本緣由就上面三種。線程

故障服務就是建立不少對象,沒法回收,致使內存不足,而後 GC 回收不了時,就會引發頻繁 FullGC 了。對象

復現故障

根據內存不足建立對象會引發 FullGC 的原理,寫了一個 Demo ,觀察GC 狀況。blog

代碼以下:

img

代碼很簡單,就是讓上次建立的對象能夠被回收,而後繼續建立對象,而後連接到根結點,使其不會被回收。demo 地址

使用啓動參數 -Xms512m -Xmx512m 設置堆內存大小。

啓動 Demo ,而後發起請求,觀察GC 狀況。

首先,使用命令 jps -l 查看進程ID

img

而後使用 jstat 命令查看GC信息 (jstat 命令詳解):

img

上圖能夠看到 正在不停的進行 Full GC.

img

上圖能夠看出,老年代,以及元數據區 內存空間已滿,這也是 不停 Full GC 的緣由。

再看我發出的請求:

img

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

使用 jstack 命令查看 線程狀態,發現 用戶線程已經被掛起。

img

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

結束語

瞭解 JVM 仍是頗有必要的。CURD 不以爲什麼,問題來臨時就能夠so easy 了。

img

相關文章
相關標籤/搜索