QQA: jstat gcutil 的輸出是什么意思
當 Java 程序有性能問題時,尤其是響應時間有突然變化時,最好第一時間查看 GC 的狀態。一般用 jstat -gcutil <pid> 1s
來查看,那么它的輸出又是什么含義呢?
輸出樣例
一般會用兩種方式調用 jstat
,一種看百分比,一種看具體數值(KB)。
例如 jstat -gcutil <pid> 1s
會每隔一秒輸出內存相關信息,示例輸出如下:
S0 S1 E O M CCS YGC YGCT FGC FGCT GCT |
而 jstat -gc <pid> 1s
會輸出具體占用的數值,如下(比較長):
S0C S1C S0U S1U EC EU OC OU MC MU YGC YGCT FGC FGCT GCT |
要理解上面輸出的具體含義,需要了解 Java 的內存與 GC 的過程。
GC 過程簡要梳理
下圖是 GC 過程的概要(圖片來源 plumbr.io):
如上圖,JVM 中的內存中的各個區域和作用如下(這里只是概述,細節麻煩查閱相關材料):
Eden
(伊甸園):創建新對象時會從中分配內存。內存不足時,觸發 Young GC。不再被引用的對象將被拋棄,還被引用的對象會被復制到 Survivor 區。Survivor
(幸存者):有兩個 Survivor 區,GC 時會來回地把內存從其中一個區復制到另一個,交替進行。這里存儲的是一些“年輕”的對象,多次 GC (默認 15 次)后這些對象還停留在 Survivor 區,則認為它們會被長期引用,Survivor 空間不足時會將它們移動到“老生代”中。來回復制的過程中除了釋放內存,還起到整理內存碎片的作用。Tenured
(終生代)、也稱Old Generation
(老生代):保留那些“長期”被引用的對象。因此該區域只在 Full GC 的時候才會被整理。PermGen
/MetaSpace
,Java 8 前是 PermGen,Java 8 后改成 MetaSpace。用來存儲諸如加載的類、字符串常量等元信息,與 GC 無關。
另外:Eden
與 Survivor
統稱“年輕代”,它們引發的 GC 也稱 “Young GC”。Young GC 通常比 Full GC 快很多,如果系統有卡頓,一般需要關注 Full GC。
jstat 輸出含義
了解了 GC 的過程,其實 jstat
的輸出通過查文檔 man jstat
就可以找到。這里權且作個翻譯:
-gcutil
的輸出如下
Column | Description |
---|---|
S0 | 第 0 個 survivor(幸存區)使用的百分比 |
S1 | 第 1 個 survivor(幸存區)使用的百分比 |
E | Eden 區使用內存的百分比 |
O | 老生代內存使用的百分比 |
P/M | PermGen /MetaSpace 的內存使用百分比 |
YGC | 程序啟動以來 Young GC 發生的次數 |
YGCT | 程序啟動以來 Young GC 共消耗的時間(s) |
FGC | 程序啟動以來 Full GC 發生的次數 |
FGCT | 程序啟動以來 Full GC 共消耗的時間(s) |
GCT | 程序啟動以來 GC 的總用時(s) |
-gc
的輸出如下
Column | Description |
---|---|
SOC | 第 0 個 Survivor 區的總空間 (KB). |
S1C | 第 1 個 Survivor 區的總空間 (KB). |
S0U | 第 0 個 Survivor 區已使用的空間 (KB). |
S1U | 第 1 個 Survivor 區已使用的空間 (KB). |
EC | Eden 區的總空間 (KB). |
EU | Eden 區已使用的空間 (KB). |
OC | OldGen 的總空間 (KB). |
OU | OldGen 已使用的空間 (KB). |
PC/MC | PermGen /MetaSpace 的總空間 (KB). |
PU/MU | PermGen /MetaSpace 使用的空間 (KB). |
YGC | 程序啟動以來 Young GC 發生的次數 |
YGCT | 程序啟動以來 Young GC 共消耗的時間(s) |
FGC | 程序啟動以來 Full GC 發生的次數 |
FGCT | 程序啟動以來 Full GC 共消耗的時間(s) |
GCT | 程序啟動以來 GC 的總用時(s) |