JVM性能调优中的命令总结
2. jstack
stack主要用來查看某個Java進程內的線程堆棧信息。
jstack主要用來查看某個Java進程內的線程堆棧信息。語法格式如下:
jstack?[option]?pid jstack?[option]?executable?core jstack?[option]?[server-id@]remote-hostname-or-ip? ? 命令行參數選項說明如下:
-l?long?listings,會打印出額外的鎖信息,在發生死鎖時可以用jstack?-l?pid來觀察鎖持有情況 -m?mixed?mode,不僅會輸出Java堆棧信息,還會輸出C/C++堆棧信息(比如Native方法)? ? jstack可以定位到線程堆棧,根據堆棧信息我們可以定位到具體代碼,所以它在JVM性能調優中使用得非常多。下面我們來一個實例找出某個Java進程中最耗費CPU的Java線程并定位堆棧信息,用到的命令有ps、top、printf、jstack、grep。
? ? 第一步先找出Java進程ID,我部署在服務器上的Java應用名稱為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? ? 得到進程ID為21711,第二步找出該進程內最耗費CPU的線程,可以使用ps -Lfp pid或者ps -mp pid -o THREAD, tid, time或者top -Hp pid,我這里用第三個,輸出如下:
? ? TIME列就是各個Java線程耗費的CPU時間,CPU時間最長的是線程ID為21742的線程,用
printf?"%x\n"?21742? ? 得到21742的十六進制值為54ee,下面會用到。 ? ?
? ? OK,下一步終于輪到jstack上場了,它用來輸出進程21711的堆棧信息,然后根據線程ID的十六進制值grep,如下:
root@ubuntu:/#?jstack?21711?|?grep?54ee "PollIntervalRetrySchedulerThread"?prio=10?tid=0x00007f950043e000?nid=0x54ee?in?Object.wait()?[0x00007f94c6eda000]? ? 可以看到CPU消耗在PollIntervalRetrySchedulerThread這個類的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)?{} }? ? 它是輪詢任務的空閑等待代碼,上面的sigLock.wait(timeUntilContinue)就對應了前面的Object.wait()。
3. jstat
jstat命令命令格式:
jstat [Options] vmid [interval] [count]參數說明:
Options,選項,我們一般使用 -gcutil 查看gc情況vmid,VM的進程號,即當前運行的java進程號
interval,間隔時間,單位為秒或者毫秒
count,打印次數,如果缺省則打印無數次
示例說明
示例
通常運行命令如下: jstat -gc 12538 5000即會每5秒一次顯示進程號為12538的java進成的GC情況, 顯示內容如下圖:
結果說明
顯示內容說明如下(部分結果是通過其他其他參數顯示的,暫不說明): S0C:年輕代中第一個survivor(幸存區)的容量 (字節)?? ? ? ? ?S1C:年輕代中第二個survivor(幸存區)的容量 (字節)?
? ? ? ? ?S0U:年輕代中第一個survivor(幸存區)目前已使用空間 (字節)?
? ? ? ? ?S1U:年輕代中第二個survivor(幸存區)目前已使用空間 (字節)?
? ? ? ? ?EC:年輕代中Eden(伊甸園)的容量 (字節)?
? ? ? ? ?EU:年輕代中Eden(伊甸園)目前已使用空間 (字節)?
? ? ? ? ?OC:Old代的容量 (字節)?
? ? ? ? ?OU:Old代目前已使用空間 (字節)?
? ? ? ? ?PC:Perm(持久代)的容量 (字節)?
? ? ? ? ?PU:Perm(持久代)目前已使用空間 (字節)?
? ? ? ? ?YGC:從應用程序啟動到采樣時年輕代中gc次數?
? ? ? ? ?YGCT:從應用程序啟動到采樣時年輕代中gc所用時間(s)?
? ? ? ? ?FGC:從應用程序啟動到采樣時old代(全gc)gc次數?
? ? ? ? ?FGCT:從應用程序啟動到采樣時old代(全gc)gc所用時間(s)?
? ? ? ? ?GCT:從應用程序啟動到采樣時gc用的總時間(s)?
? ? ? ? ?NGCMN:年輕代(young)中初始化(最小)的大小 (字節)?
? ? ? ? ?NGCMX:年輕代(young)的最大容量 (字節)?
? ? ? ? ?NGC:年輕代(young)中當前的容量 (字節)?
? ? ? ? ?OGCMN:old代中初始化(最小)的大小 (字節)?
? ? ? ? ?OGCMX:old代的最大容量 (字節)?
? ? ? ? ?OGC:old代當前新生成的容量 (字節)?
? ? ? ? ?PGCMN:perm代中初始化(最小)的大小 (字節)?
? ? ? ? ?PGCMX:perm代的最大容量 (字節) ??
? ? ? ? ?PGC:perm代當前新生成的容量 (字節)?
? ? ? ? ?S0:年輕代中第一個survivor(幸存區)已使用的占當前容量百分比?
? ? ? ? ?S1:年輕代中第二個survivor(幸存區)已使用的占當前容量百分比?
? ? ? ? ?E:年輕代中Eden(伊甸園)已使用的占當前容量百分比?
? ? ? ? ?O:old代已使用的占當前容量百分比?
? ? ? ? ?P:perm代已使用的占當前容量百分比?
? ? ? ? ?S0CMX:年輕代中第一個survivor(幸存區)的最大容量 (字節)?
? ? ? ? ?S1CMX :年輕代中第二個survivor(幸存區)的最大容量 (字節)?
? ? ? ? ?ECMX:年輕代中Eden(伊甸園)的最大容量 (字節)?
? ? ? ? ?DSS:當前需要survivor(幸存區)的容量 (字節)(Eden區已滿)?
? ? ? ? ?TT: 持有次數限制?
? ? ? ? ?MTT : 最大持有次數限制
要明白上面各列的意義,先看JVM堆內存布局:
? ? 可以看出:
堆內存?=?年輕代?+?年老代?+?永久代 年輕代?=?Eden區?+?兩個Survivor區(From和To)4. jmap
使用jmap查看Java進程對象使用情況
運行命令
使用jmap可以查看某個Java進程中每個對象有多少個實例,占用多少內存, 命令格式: jmap -histo?進程id示例說明
例如運行: jmap -histo ?12538 顯示結果如下圖(內容較多, 分成幾張圖說明): 內容開始部分內容結束部分
上圖中: 第一列,序號,無實際意義 第二列,對象實例數量 第三列,對象實例占用總內存數,單位:字節 第四列,對象實例名稱 最后一行,總實例數量與總內存占用數
還有一個很常用的情況是:用jmap把進程內存使用情況dump到文件中,再用jhat分析查看。jmap進行dump命令格式如下:
jmap?-dump:format=b,file=dumpFileName pid? ? 我一樣地對上面進程ID為21711進行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這種參數指定最大堆內存,即jhat -J-Xmx512m -port 9998 /tmp/dump.dat。然后就可以在瀏覽器中輸入主機地址:9998查看了:
? ? 上面紅線框出來的部分大家可以自己去摸索下,最后一項支持OQL(對象查詢語言)。
總結
以上是生活随笔為你收集整理的JVM性能调优中的命令总结的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: arcgis api for javas
- 下一篇: Scala入门到精通——第三十节 Sca