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