摘要:原文鏈接這是專家系列文章的第二篇。運行在本地虛擬機上的應用的又稱為,通常與相同。性能數據需要持續觀察,因此在運行時需要定時輸出的監控信息。新生代容量的統計信息。是提供的一個式的圖表監控工具。
原文鏈接:http://www.cubrid.org/blog/dev-platform/how-to-monitor-java-garbage-collection/
這是GC專家系列文章的第二篇。在第一篇理解Java垃圾回收中我們學習了幾種不同的GC算法的處理過程,GC的工作方式,新生代與老年代的區別。到目前為止,你應該已經了解了JDK 7中的5種GC類型,以及每種GC對性能的影響。
在本篇中,我將介紹JVM在真實環境中如何運行GC的。
什么是GC監控GC監控 指的是在運行時跟蹤JVM運行GC的過程。例如,通過GC監控,我們能找出:
何時新生代的對象會被移動到老年代,有多少對象被移到了老年代。
何時stop-the-world發生以及持續時間。
通過GC監控,能發現JVM是否在有效的運行GC以及是否需要額外的GC調優。基于這些信息,我們可以通過優化應用或者改變GC運行方式(GC調優),從而提高應用性能。
如何做GC監控GC監控的方式很多,區別在于GC操作信息的展示會有所不同。GC是由JVM觸發,因為GC監控工具展示的信息都是由JVM提供,所以不管使用哪種方式做GC監控,最終獲取的信息都是一致的。因此,沒有必要深入學習每種GC監控工具,只需要花些時間學習每種工具的使用方法,能夠在不同的場合選擇合適的工具即可。
因為JVM規范沒有要求暴露GC信息的標準方法,所以下面列出的工具或JVM選項并不能適用于所有不同的JVM實現。在下面的介紹中都是基于Hotspot JVM(Oracle JVM)進行。因為NHN使用的是Oracle(Sun) JVM,所以在使用以下工具或JVM選項時并不會太困難。
首先,GC監控工具根據訪問接口和方式不同分為CUI和GUI。經典的CUI 工具可以使用一個多帶帶的CUI應用jstat,也可以在運行JVM時通過提供"-verbosegc"選項來實現。
GUI GC監控工具通過多帶帶的GUI應用來實現,后面會介紹三個常用的GUI GC工具:jconsole, jvisualvm和Visual GC。
下面開始學習每一種GC監控方法:
jstatjstat是Hotspot JVM內置的監控工具。Hotspot JVM還內置了其他監控工具如jps和jstatd。有時候需要這三種工具一起來監控Java應用的運行。
jstat 不只提供GC操作的相關信息,也還提供類加載和即時編譯器相關的操作信息。盡管如此,本文我們只會涉及jstat提供的GC操作相關的功能。
jstat 位于$JDK_HOME/bin目錄,如果java或javac命令能夠正常運行,jstat命令也應該能夠運行。
你可以在命令行中嘗試一下:
$> jstat –gc $1000 S0C S1C S0U S1U EC EU OC OU PC PU YGC YGCT FGC FGCT GCT 3008.0 3072.0 0.0 1511.1 343360.0 46383.0 699072.0 283690.2 75392.0 41064.3 2540 18.454 4 1.133 19.588 3008.0 3072.0 0.0 1511.1 343360.0 47530.9 699072.0 283690.2 75392.0 41064.3 2540 18.454 4 1.133 19.588 3008.0 3072.0 0.0 1511.1 343360.0 47793.0 699072.0 283690.2 75392.0 41064.3 2540 18.454 4 1.133 19.588 $>
如上所示,真實的內存各部分數據情況按以下各列順序列出:
SOC S1C S0U S1U EC EU OU PC
vmid(虛擬機id: Virtual Machine ID),見名示意,表示VM的ID。運行在本地或遠程的虛擬機都可以通過vmid指定。運行在本地虛擬機上的Java應用的vmid又稱為lvmid(Local vmid),通常與PID相同。雖然可以通過ps命令或Windows的任務管理器查看PID的值從而得到lvmid,但更推薦使用jps,因為PID和lvmid之間并不總是一一對應。jps表示Java PS。正如ps命令可以看到PIDs和進程名,通過jps可以看到vmids和main方法信息。
通過jps找到你要監控的Java應用的vmid,然后作為jstat的參數即可。如果多個WAS實例運行在同一設備上時,如果只使用jps命令只能找到引導程序的信息。這時候就要ps -ef | grep java命令和jps命令一起使用。
GC性能數據需要持續觀察,因此在運行jstat時需要定時輸出GC的監控信息。
舉例來說:運行jstat -gc
與GC相關的選項除了-gc,還有其他一些,如下表所示:
選項名稱 | 描述 |
---|---|
gc | 輸出堆空間上各分區當前的大小及使用量(Ede, Survivor, Old等),GC執行的總次數以及累積消耗的執行時長。 |
gccapacity | 輸出堆空間上各分區的最小和最大容量,當前大小,每個區上的GC執行次數(不輸出當前使用量和累積的GC耗時)。 |
gccause | 除了輸出 -gcutil提供的信息外,還會輸出最后一次GC和當前GC的原因。 |
gcnew | 新生代上的GC性能數據。 |
gcnewcapacity | 新生代容量的統計信息。 |
gcold | 老年代的GC性能數據。 |
gcoldcapacity | 老年代容量的統計信息。 |
gcpermcapacity | 持久代(方法區)上的統計信息。 |
gcutil | 以%的格式輸出每個分區的使用量。同時也會輸出GC執行的總次數及累積耗時。 |
如果只關心GC頻率,通常使用-gcutil(或者 -gccause), -gc, -gccapacity即可。
-gcutil 用于檢測各區上的使用量,GC執行次數以及累積耗時,
-gccapacity 和其他的幾個選項可用于輸出實際已分配的內存大小。
使用-gc選項的輸出如下:
S0C S1C … GCT 1248.0 896.0 … 1.246 1248.0 896.0 … 1.246 … … … …
給jstat指定不同的選項會列出不同的列,如下列所示。表格右側列出了會輸出此信息的jstat選項。
數據列 | 描述 | 支持的jstat 選項 |
---|---|---|
S0C | Survivor0的當前容量 | -gc -gccapacity -gcnew -gcnewcapacity |
S1C | S1的當前容量 | -gc -gccapacity -gcnew -gcnewcapacity |
S0U | S0的使用量 | -gc -gcnew |
S1U | S1的使用量 | -gc -gcnew |
EC | Eden區的當前容量 | -gc -gccapacity -gcnew -gcnewcapacity |
EU | Eden區的使用量 | -gc -gcnew |
OC | old區的當前容量 | -gc -gccapacity -gcnew -gcnewcapacity |
OU | old區的使用量 | -gc -gcnew |
PC | 方法區的當前容量 | -gc -gccapacity -gcold -gcoldcapacity -gcpermcapacity |
PU | 方法區的使用量 | -gc -gcold |
YGC | Young GC次數 | -gc -gccapacity -gcnew -gcnewcapacity -gcold -gcoldcapacity -gcpermcapacity -gcutil -gccause |
YGCT | Young GC累積耗時 | -gc -gcnew -gcutil -gccause |
FGC | Full GC次數 | -gc -gccapacity -gcnew -gcnewcapacity -gcold -gcoldcapacity -gcpermcapacity -gcutil -gccause |
FGCT | Full GC累積耗時 | -gc -gcold -gcoldcapacity -gcpermcapacity -gcutil -gccause |
GCT | GC總的累積耗時 | -gc -gcold -gcoldcapacity -gccapacity -gcpermcapacity -gcutil -gccause |
NGCMN | 新生代最小容量 | -gccapacity -gcnewcapacity |
NGCMX | 新生代最大容量 | -gccapacity -gcnewcapacity |
NGC | 新生代當前容量 | -gccapacity -gcnewcapacity |
OGCMN | 老年代最小容量 | -gccapacity -gcoldcapacity |
OGCMX | 老年代最大容量 | -gccapacity -gcoldcapacity |
OGC | 老年代當前容量 | -gccapacity -gcoldcapacity |
PGCMN | 方法區最小容量 | -gccapacity -gcpermcapacity |
PGCMX | 方法區最大容量 | -gccapacity -gcpermcapacity |
PGC | 方法區當前容量 | -gccapacity -gcpermcapacity |
PC | 方法區的當前容量 | -gccapacity -gcpermcapacity |
PU | 方法區使用量 | -gccapacity -gcold |
LGCC | 上一次GC發生的原因 | -gccause |
GCC | 當前GC發生的原因 | -gccause |
TT | 存活閥值,如果對象在新生代移動次數超過此閥值,則會被移到老年代 | -gcnew |
MTT | 最大存活閥值,如果對象在新生代移動次數超過此閥值,則會被移到老年代 | -gcnew |
DSS | survivor區的理想容量 | -gcnew |
表格中容量數量單位為:KB
jstat的優點在于不管是本地還是遠程Java應用,你都可以通過jstat命令查看GC操作相關的數據,并通過控制臺輸出這些信息。在使用-gcutil選項時,會輸出如下字段的信息。在做GC調優時,尤其要關注YGC, YGCT, FGC, FGCT和GCT的數據變化。
S0 S1 E O P YGC YGCT FGC FGCT GCT 0.00 66.44 54.12 10.58 86.63 217 0.928 2 0.067 0.995 0.00 66.44 54.12 10.58 86.63 217 0.928 2 0.067 0.995 0.00 66.44 54.12 10.58 86.63 217 0.928 2 0.067 0.995
這些信息非常重要,它統計了GC運行時的耗時情況,能反映出GC的性能指標。
在上例中,YGC是217次, YGCT為0.928,平均下來每次young GC耗時4ms(0.004 s)。同樣可算出full GC的平均耗時為33ms。
然而平均值對發現實現的GC問題并沒有太大的幫助,因為每次GC耗時通常會有巨大的偏差(也就是說,如果full GC的平均值為0.067s,可能意味著其中一次GC耗時1ms,而另外一次持續134ms)。為了能觀察每次GC的獨立耗時而非平均值,更好的方式是使用-verbosegc。
-verbosegc-verbosegc 是運行Java應用時的一個JVM選項。jstat可以監控任何JVM應用而無需指定啟動參數,-verbosegc去要在開啟應用時就指定好,所以看起來-verbosegc并不是一個必要的選項(因為可以使用jstat完成相同工作)。然而當GC發生時-verbosegc的輸出信息更容易理解,這對于監控煩雜的GC信息卻大于益處。
jstat | -verbosegc | |
---|---|---|
監控目標 | 可輸出日志到終端上的Java應用或者能通過jstatd連接到網絡的遠程Java應用 | 在啟動JVM時指定了-verbosegc 參數的Java應用 |
輸出信息 | 堆狀態(使用量、最大容量、GC次數及累積耗時等) | 每次GC前后新生代和老年代的容量變化及GC耗時 |
輸出時機 | 任何指定的時間 | 任何GC發生時 |
優勢 | 方便連續觀察堆大小的變化 | 觀察單次GC對系統的影響 |
在使用-verbosegc時還可同時指定以下附加選項:
-XX:+PrintGCDetails
-XX:+PrintGCTimeStamps
-XX:+PrintHeapAtGC
-XX:+PrintGCDateStamps(JDK6U4引入的選項)
如果只是指定了-verbosegc選項,則默認會同時指定-XX:+PrintGCDetails。另外,-verbosegc的附加選項都可以組合使用。
使用-verbosegc后,當有minor GC發生時,輸出的數據格式如下:
[GC [: -> , secs] -> , secs]
字段 | 含義 | |
---|---|---|
Collector | 使用的收集器 | |
starting occupancy1 | GC發生前的新生代大小 | |
ending occupancy1 | GC后新生代的大小 | |
pause time1 | 執行minor GC時Java應用停頓的時長 | |
starting occupancy3 | GC發生前堆空間總大小 | |
ending occupancy3 | GC發生后堆空間總大小 | |
pause time3 | 執行總體GC(包括Full GC)時Java應用停頓時長 |
下面是一個Full GC輸出的例子:
[Full GC [Tenured: 3485K->4095K(4096K), 0.1745373 secs] 61244K->7418K(63104K), [Perm : 10756K->10756K(12288K)], 0.1762129 secs] [Times: user=0.19 sys=0.00, real=0.19 secs]
如果使用了[CMS回收算法](),CMS相關信息也會緊接著提供出來。
因為-verbosegc選項可以把每次GC發生時的信息都以log方式輸出,所以很容易觀察GC操作關后heap使用率的變化情況。
(Java) VisualVM + Visual GCJava Virsual VM是Oracle JDK提供的一個GUI式的圖表/監控工具。
圖1:VirsualVM 界面
與內置在JDK中的版本不同,你可以在網站上多帶帶下載Virsual VM。方便起見,JDK內置的版本稱為Java VirsualVM(jvisualvm),從網站上多帶帶下載的稱為Virsual VM(visualvm)。二者之間的特性并不完全一致,在一些方面(例如安裝插件等)會有細微的差別。就我個人而言,更偏向于使用多帶帶下載的Virsual VM。
啟動Visual VM后,如果你左側面板上選擇了希望監控的應用,就會看到"Monitoring"一欄。從Monitoring欄中可以獲得關于GC和內存堆的基本信息。
盡管能通過Visual VM的基本特性得到GC的基本狀態,但并不能像使用jstat和-verbosegc一樣獲得更詳細的信息。
如果想得到像jstat一樣的詳細信息,則需要安裝相應的Virsual VM插件。可以在Tools菜單里獲取Virsual GC插件。
圖2:Virsual GC安裝界面
通過Virsual GC,可以以更直觀的方式獲得jstatd提供的信息。
圖3:Virsual GC運行界面
HPJMeter是一個分析-verbosegc輸出結果的便捷工具。如果把Visual GC看作是jstat的GUI版本,那么HPJMeter則是-verbosegc的GUI版本。話說回來,GC分析只是HPJMeter提供的眾多特性之一。HPJMeter是HP公司開發的一款性能監控工具,可以使用在HP-UX,Linux和MS Windows上。
起初,只是一款叫做HPTune的工具提供GUI的方式分析-verbosegc。自從HPJMeter 3.0開始便集成了HPTune,因此無需再多帶帶下載HPTune。
在應用運行過程中,-verbosegc的輸出結果可以重定向到一個多帶帶的文件中。
可以通過HPJMeter打開該文件,然后使用直觀的GUI界面便捷的分析GC數據。
圖4:HPJMeter
本章作為GC調優的鋪墊,著重于介紹了如何進行GC信息監控。一般情況我比較建議先使用jstat觀察GC操作,當發現有比較耗時的GC后,再通過-verbosegc來分析GC數據。因此GC調優的一般過程就是分析和對比使用不同GC選項后-verbosegc輸出結果的變化。下章將會通過真實案例來介紹進行GC調優的最佳選項。
作者:Sangmin Lee, 性能實驗室高級工程師,NHN公司
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/65367.html
摘要:本文是成為專家系列的第一篇。然而,在多線程環境下,將會有別樣的狀況。在中正是通過解決了多線程問題。在最后的并發清理階段,垃圾回收過程被真正執行。在垃圾回收執行過程中,其他線程依然在執行。 原文鏈接:http://www.cubrid.org/blog/de... 了解Java的垃圾回收(GC)原理能給我們帶來什么好處?對于軟件工程師來說,滿足技術好奇心可算是一個,但重要的是理解GC能幫...
摘要:在本文中我將會介紹應用性能優化的一般原則。性能優化的流程圖摘取自和合著的性能,描述了應用性能優化的處理流程。例如,對每臺服務器,你面臨著為單個分配堆內存和運行個并為每個分配堆內存的選擇。不過位能使用堆內存最大理論值只有。 原文鏈接:http://www.cubrid.org/blog/dev-platform/the-principles-of-java-application-per...
摘要:本文將介紹的參數的重要性以及在發生時對系統整體性能的顯著影響。我們來看下的選項在發生時會對系統帶來哪些影響。所以這些請求將會放到堆積隊列,隊列的長度是的中設置的。從而導致進程的數量超過,并觸發了操作系統進行內存交換的閥值。 原文鏈接:http://www.cubrid.org/blog/dev-platform/maxclients-in-apache-and-its-effect-o...
摘要:原文鏈接本篇是專家系列的第三篇。但是,請記住調優是不得已時的選擇。縮短耗時的單次執行與相比,耗時有較明顯的增加。創建文件過程中,進程會中斷,因此不要在正常運行時系統上做此操作。因此校驗結果并根據具體的服務需要,決定是否要進行調優。 原文鏈接:http://www.cubrid.org/blog/dev-platform/how-to-tune-java-garbage-collecti...
摘要:調優調優中基于真實案例介紹了可用于調優的最佳選項。的設置及其對的影響的設置及其對的影響中介紹了對選項在系統發生時對整體性能的影響。具體來說,我會介紹性能優化的必要條件判斷是否需要優化的步驟,同時也會列出在性能優化過程中經遇到的一些問題。 1. 理解Java垃圾回收 理解Java垃圾回收中我們學習了幾種不同的GC算法的處理過程,GC的工作方式,新生代與老年代的區別。所以,你應該已經了解...
閱讀 2609·2021-11-17 17:00
閱讀 1864·2021-10-11 10:57
閱讀 3716·2021-09-09 11:33
閱讀 911·2021-09-09 09:33
閱讀 3550·2019-08-30 14:20
閱讀 3312·2019-08-29 11:25
閱讀 2796·2019-08-26 13:48
閱讀 734·2019-08-26 11:52