JVM性能调优中的命令总结
2. jstack
stack主要用來查看某個(gè)Java進(jìn)程內(nèi)的線程堆棧信息。
jstack主要用來查看某個(gè)Java進(jìn)程內(nèi)的線程堆棧信息。語法格式如下:
jstack?[option]?pid jstack?[option]?executable?core jstack?[option]?[server-id@]remote-hostname-or-ip? ? 命令行參數(shù)選項(xiàng)說明如下:
-l?long?listings,會(huì)打印出額外的鎖信息,在發(fā)生死鎖時(shí)可以用jstack?-l?pid來觀察鎖持有情況 -m?mixed?mode,不僅會(huì)輸出Java堆棧信息,還會(huì)輸出C/C++堆棧信息(比如Native方法)? ? jstack可以定位到線程堆棧,根據(jù)堆棧信息我們可以定位到具體代碼,所以它在JVM性能調(diào)優(yōu)中使用得非常多。下面我們來一個(gè)實(shí)例找出某個(gè)Java進(jìn)程中最耗費(fèi)CPU的Java線程并定位堆棧信息,用到的命令有ps、top、printf、jstack、grep。
? ? 第一步先找出Java進(jìn)程ID,我部署在服務(wù)器上的Java應(yīng)用名稱為mrf-center:
root@ubuntu:/#?ps?-ef?|?grep?mrf-center?|?grep?-v?grep root?????21711?????1??1?14:47?pts/3????00:02:10?java?-jar?mrf-center.jar? ? 得到進(jìn)程ID為21711,第二步找出該進(jìn)程內(nèi)最耗費(fèi)CPU的線程,可以使用ps -Lfp pid或者ps -mp pid -o THREAD, tid, time或者top -Hp pid,我這里用第三個(gè),輸出如下:
? ? TIME列就是各個(gè)Java線程耗費(fèi)的CPU時(shí)間,CPU時(shí)間最長的是線程ID為21742的線程,用
printf?"%x\n"?21742? ? 得到21742的十六進(jìn)制值為54ee,下面會(huì)用到。 ? ?
? ? OK,下一步終于輪到j(luò)stack上場了,它用來輸出進(jìn)程21711的堆棧信息,然后根據(jù)線程ID的十六進(jìn)制值grep,如下:
root@ubuntu:/#?jstack?21711?|?grep?54ee "PollIntervalRetrySchedulerThread"?prio=10?tid=0x00007f950043e000?nid=0x54ee?in?Object.wait()?[0x00007f94c6eda000]? ? 可以看到CPU消耗在PollIntervalRetrySchedulerThread這個(gè)類的Object.wait(),我找了下我的代碼,定位到下面的代碼:
//?Idle?wait getLog().info("Thread?["?+?getName()?+?"]?is?idle?waiting..."); schedulerThreadState?=?PollTaskSchedulerThreadState.IdleWaiting; long?now?=?System.currentTimeMillis(); long?waitTime?=?now?+?getIdleWaitTime(); long?timeUntilContinue?=?waitTime?-?now; synchronized(sigLock)?{try?{if(!halted.get())?{sigLock.wait(timeUntilContinue);}}?catch?(InterruptedException?ignore)?{} }? ? 它是輪詢?nèi)蝿?wù)的空閑等待代碼,上面的sigLock.wait(timeUntilContinue)就對應(yīng)了前面的Object.wait()。
3. jstat
jstat命令命令格式:
jstat [Options] vmid [interval] [count]參數(shù)說明:
Options,選項(xiàng),我們一般使用 -gcutil 查看gc情況vmid,VM的進(jìn)程號(hào),即當(dāng)前運(yùn)行的java進(jìn)程號(hào)
interval,間隔時(shí)間,單位為秒或者毫秒
count,打印次數(shù),如果缺省則打印無數(shù)次
示例說明
示例
通常運(yùn)行命令如下: jstat -gc 12538 5000即會(huì)每5秒一次顯示進(jìn)程號(hào)為12538的java進(jìn)成的GC情況, 顯示內(nèi)容如下圖:
結(jié)果說明
顯示內(nèi)容說明如下(部分結(jié)果是通過其他其他參數(shù)顯示的,暫不說明): S0C:年輕代中第一個(gè)survivor(幸存區(qū))的容量 (字節(jié))?? ? ? ? ?S1C:年輕代中第二個(gè)survivor(幸存區(qū))的容量 (字節(jié))?
? ? ? ? ?S0U:年輕代中第一個(gè)survivor(幸存區(qū))目前已使用空間 (字節(jié))?
? ? ? ? ?S1U:年輕代中第二個(gè)survivor(幸存區(qū))目前已使用空間 (字節(jié))?
? ? ? ? ?EC:年輕代中Eden(伊甸園)的容量 (字節(jié))?
? ? ? ? ?EU:年輕代中Eden(伊甸園)目前已使用空間 (字節(jié))?
? ? ? ? ?OC:Old代的容量 (字節(jié))?
? ? ? ? ?OU:Old代目前已使用空間 (字節(jié))?
? ? ? ? ?PC:Perm(持久代)的容量 (字節(jié))?
? ? ? ? ?PU:Perm(持久代)目前已使用空間 (字節(jié))?
? ? ? ? ?YGC:從應(yīng)用程序啟動(dòng)到采樣時(shí)年輕代中g(shù)c次數(shù)?
? ? ? ? ?YGCT:從應(yīng)用程序啟動(dòng)到采樣時(shí)年輕代中g(shù)c所用時(shí)間(s)?
? ? ? ? ?FGC:從應(yīng)用程序啟動(dòng)到采樣時(shí)old代(全gc)gc次數(shù)?
? ? ? ? ?FGCT:從應(yīng)用程序啟動(dòng)到采樣時(shí)old代(全gc)gc所用時(shí)間(s)?
? ? ? ? ?GCT:從應(yīng)用程序啟動(dòng)到采樣時(shí)gc用的總時(shí)間(s)?
? ? ? ? ?NGCMN:年輕代(young)中初始化(最小)的大小 (字節(jié))?
? ? ? ? ?NGCMX:年輕代(young)的最大容量 (字節(jié))?
? ? ? ? ?NGC:年輕代(young)中當(dāng)前的容量 (字節(jié))?
? ? ? ? ?OGCMN:old代中初始化(最小)的大小 (字節(jié))?
? ? ? ? ?OGCMX:old代的最大容量 (字節(jié))?
? ? ? ? ?OGC:old代當(dāng)前新生成的容量 (字節(jié))?
? ? ? ? ?PGCMN:perm代中初始化(最小)的大小 (字節(jié))?
? ? ? ? ?PGCMX:perm代的最大容量 (字節(jié)) ??
? ? ? ? ?PGC:perm代當(dāng)前新生成的容量 (字節(jié))?
? ? ? ? ?S0:年輕代中第一個(gè)survivor(幸存區(qū))已使用的占當(dāng)前容量百分比?
? ? ? ? ?S1:年輕代中第二個(gè)survivor(幸存區(qū))已使用的占當(dāng)前容量百分比?
? ? ? ? ?E:年輕代中Eden(伊甸園)已使用的占當(dāng)前容量百分比?
? ? ? ? ?O:old代已使用的占當(dāng)前容量百分比?
? ? ? ? ?P:perm代已使用的占當(dāng)前容量百分比?
? ? ? ? ?S0CMX:年輕代中第一個(gè)survivor(幸存區(qū))的最大容量 (字節(jié))?
? ? ? ? ?S1CMX :年輕代中第二個(gè)survivor(幸存區(qū))的最大容量 (字節(jié))?
? ? ? ? ?ECMX:年輕代中Eden(伊甸園)的最大容量 (字節(jié))?
? ? ? ? ?DSS:當(dāng)前需要survivor(幸存區(qū))的容量 (字節(jié))(Eden區(qū)已滿)?
? ? ? ? ?TT: 持有次數(shù)限制?
? ? ? ? ?MTT : 最大持有次數(shù)限制
要明白上面各列的意義,先看JVM堆內(nèi)存布局:
? ? 可以看出:
堆內(nèi)存?=?年輕代?+?年老代?+?永久代 年輕代?=?Eden區(qū)?+?兩個(gè)Survivor區(qū)(From和To)4. jmap
使用jmap查看Java進(jìn)程對象使用情況
運(yùn)行命令
使用jmap可以查看某個(gè)Java進(jìn)程中每個(gè)對象有多少個(gè)實(shí)例,占用多少內(nèi)存, 命令格式: jmap -histo?進(jìn)程id示例說明
例如運(yùn)行: jmap -histo ?12538 顯示結(jié)果如下圖(內(nèi)容較多, 分成幾張圖說明): 內(nèi)容開始部分內(nèi)容結(jié)束部分
上圖中: 第一列,序號(hào),無實(shí)際意義 第二列,對象實(shí)例數(shù)量 第三列,對象實(shí)例占用總內(nèi)存數(shù),單位:字節(jié) 第四列,對象實(shí)例名稱 最后一行,總實(shí)例數(shù)量與總內(nèi)存占用數(shù)
還有一個(gè)很常用的情況是:用jmap把進(jìn)程內(nèi)存使用情況dump到文件中,再用jhat分析查看。jmap進(jìn)行dump命令格式如下:
jmap?-dump:format=b,file=dumpFileName pid? ? 我一樣地對上面進(jìn)程ID為21711進(jìn)行Dump:
root@ubuntu:/#?jmap?-dump:format=b,file=/tmp/dump.dat?21711????? Dumping?heap?to?/tmp/dump.dat?... Heap?dump?file?created? ?dump出來的文件可以用MAT、VisualVM等工具查看,這里用jhat查看:
root@ubuntu:/#?jhat?-port?9998?/tmp/dump.dat Reading?from?/tmp/dump.dat... Dump?file?created?Tue?Jan?28?17:46:14?CST?2014 Snapshot?read,?resolving... Resolving?132207?objects... Chasing?references,?expect?26?dots.......................... Eliminating?duplicate?references.......................... Snapshot?resolved. Started?HTTP?server?on?port?9998 Server?is?ready.? ? ?注意如果Dump文件太大,可能需要加上-J-Xmx512m這種參數(shù)指定最大堆內(nèi)存,即jhat -J-Xmx512m -port 9998 /tmp/dump.dat。然后就可以在瀏覽器中輸入主機(jī)地址:9998查看了:
? ? 上面紅線框出來的部分大家可以自己去摸索下,最后一項(xiàng)支持OQL(對象查詢語言)。
總結(jié)
以上是生活随笔為你收集整理的JVM性能调优中的命令总结的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: arcgis api for javas
- 下一篇: Scala入门到精通——第三十节 Sca