JVM监控工具介绍jstack, jconsole, jinfo, jmap, jdb, jstat
http://my.oschina.net/timer/blog/10599
jstack?-- 如果java程序崩潰生成core文件,jstack工具可以用來獲得core文件的java stack和native stack的信息,從而可以輕松地知道java程序是如何崩潰和在程序何處發(fā)生問題。另外,jstack工具還可以附屬到正在運(yùn)行的java程序中,看到當(dāng)時(shí)運(yùn)行的java程序的java stack和native stack的信息, 如果現(xiàn)在運(yùn)行的java程序呈現(xiàn)hung的狀態(tài),jstack是非常有用的。目前只有在Solaris和Linux的JDK版本里面才有。
jconsole?– jconsole是基于Java?Management Extensions (JMX)的實(shí)時(shí)圖形化監(jiān)測(cè)工具,這個(gè)工具利用了內(nèi)建到JVM里面的JMX指令來提供實(shí)時(shí)的性能和資源的監(jiān)控,包括了Java程序的內(nèi)存使用,Heap size, 線程的狀態(tài),類的分配狀態(tài)和空間使用等等。
jinfo?– jinfo可以從core文件里面知道崩潰的Java應(yīng)用程序的配置信息,目前只有在Solaris和Linux的JDK版本里面才有。
jmap?– jmap 可以從core文件或進(jìn)程中獲得內(nèi)存的具體匹配情況,包括Heap size, Perm size等等,目前只有在Solaris和Linux的JDK版本里面才有。
jdb?– jdb 用來對(duì)core文件和正在運(yùn)行的Java進(jìn)程進(jìn)行實(shí)時(shí)地調(diào)試,里面包含了豐富的命令幫助您進(jìn)行調(diào)試,它的功能和Sun studio里面所帶的dbx非常相似,但 jdb是專門用來針對(duì)Java應(yīng)用程序的。
jstat?– jstat利用了JVM內(nèi)建的指令對(duì)Java應(yīng)用程序的資源和性能進(jìn)行實(shí)時(shí)的命令行的監(jiān)控,包括了對(duì)Heap size和垃圾回收狀況的監(jiān)控等等。
jps?– jps是用來查看JVM里面所有進(jìn)程的具體狀態(tài), 包括進(jìn)程ID,進(jìn)程啟動(dòng)的路徑等等。?
jstatd
啟動(dòng)jvm監(jiān)控服務(wù)。它是一個(gè)基于rmi的應(yīng)用,向遠(yuǎn)程機(jī)器提供本機(jī)jvm應(yīng)用程序的信息。默認(rèn)端口1099。
實(shí)例:jstatd -J-Djava.security.policy=my.policy
my.policy文件需要自己建立,內(nèi)如如下:
grant codebase "file:$JAVA_HOME/lib/tools.jar" {
?permission java.security.AllPermission;
};
這是安全策略文件,因?yàn)閖dk對(duì)jvm做了jaas的安全檢測(cè),所以我們必須設(shè)置一些策略,使得jstatd被允許作網(wǎng)絡(luò)操作
上面的操作沒有通過,出現(xiàn):
Could not create remote object
access denied (java.util.PropertyPermission java.rmi.server.ignoreSubClasses write)
java.security.AccessControlException: access denied (java.util.PropertyPermission java.rmi.server.ignoreSubClasses write)
??????? at java.security.AccessControlContext.checkPermission(AccessControlContext.java:323)
??????? at java.security.AccessController.checkPermission(AccessController.java:546)
??????? at java.lang.SecurityManager.checkPermission(SecurityManager.java:532)
??????? at java.lang.System.setProperty(System.java:727)
??????? at sun.tools.jstatd.Jstatd.main(Jstatd.java:122)
create in your usr/java/bin the jstatd.all.policy file, with the content must be
jps
列出所有的jvm實(shí)例
實(shí)例:
jps
列出本機(jī)所有的jvm實(shí)例
jps 192.168.0.77
列出遠(yuǎn)程服務(wù)器192.168.0.77機(jī)器所有的jvm實(shí)例,采用rmi協(xié)議,默認(rèn)連接端口為1099
(前提是遠(yuǎn)程服務(wù)器提供jstatd服務(wù))
輸出內(nèi)容如下:
jones@jones:~/data/ebook/java/j2se/jdk_gc$ jps
6286 Jps
6174? Jstat
jconsole
一個(gè)圖形化界面,可以觀察到j(luò)ava進(jìn)程的gc,class,內(nèi)存等信息。雖然比較直觀,但是個(gè)人還是比較傾向于使用jstat命令(在最后一部分會(huì)對(duì)jstat作詳細(xì)的介紹)。
jinfo(linux下特有)
觀察運(yùn)行中的java程序的運(yùn)行環(huán)境參數(shù):參數(shù)包括Java System屬性和JVM命令行參數(shù)
實(shí)例:jinfo 2083
其中2083就是java進(jìn)程id號(hào),可以用jps得到這個(gè)id號(hào)。
輸出內(nèi)容太多了,不在這里一一列舉,大家可以自己嘗試這個(gè)命令。
jstack(linux下特有)
可以觀察到j(luò)vm中當(dāng)前所有線程的運(yùn)行情況和線程當(dāng)前狀態(tài)
jstack 2083
輸出內(nèi)容如下:
jmap(linux下特有,也是很常用的一個(gè)命令)
觀察運(yùn)行中的jvm物理內(nèi)存的占用情況。
參數(shù)如下:
-heap:打印jvm heap的情況
-histo:打印jvm heap的直方圖。其輸出信息包括類名,對(duì)象數(shù)量,對(duì)象占用大小。
-histo:live :同上,但是只答應(yīng)存活對(duì)象的情況
-permstat:打印permanent generation heap情況
命令使用:
jmap -heap 2083
可以觀察到New Generation(Eden Space,From Space,To Space),tenured generation,Perm Generation的內(nèi)存使用情況
輸出內(nèi)容:
jmap -histo 2083 | jmap -histo:live 2083
可以觀察heap中所有對(duì)象的情況(heap中所有生存的對(duì)象的情況)。包括對(duì)象數(shù)量和所占空間大小。
輸出內(nèi)容:
寫個(gè)腳本,可以很快把占用heap最大的對(duì)象找出來,對(duì)付內(nèi)存泄漏特別有效。
jstat
最后要重點(diǎn)介紹下這個(gè)命令。
這是jdk命令中比較重要,也是相當(dāng)實(shí)用的一個(gè)命令,可以觀察到classloader,compiler,gc相關(guān)信息
具體參數(shù)如下:
-class:統(tǒng)計(jì)class loader行為信息
-compile:統(tǒng)計(jì)編譯行為信息
-gc:統(tǒng)計(jì)jdk gc時(shí)heap信息
-gccapacity:統(tǒng)計(jì)不同的generations(不知道怎么翻譯好,包括新生區(qū),老年區(qū),permanent區(qū))相應(yīng)的heap容量情況
-gccause:統(tǒng)計(jì)gc的情況,(同-gcutil)和引起gc的事件
-gcnew:統(tǒng)計(jì)gc時(shí),新生代的情況
-gcnewcapacity:統(tǒng)計(jì)gc時(shí),新生代heap容量
-gcold:統(tǒng)計(jì)gc時(shí),老年區(qū)的情況
-gcoldcapacity:統(tǒng)計(jì)gc時(shí),老年區(qū)heap容量
-gcpermcapacity:統(tǒng)計(jì)gc時(shí),permanent區(qū)heap容量
-gcutil:統(tǒng)計(jì)gc時(shí),heap情況
-printcompilation:不知道干什么的,一直沒用過。
一般比較常用的幾個(gè)參數(shù)是:
jstat -class 2083 1000 10 (每隔1秒監(jiān)控一次,一共做10次)
輸出內(nèi)容含義如下:
| Loaded | Number of classes loaded. |
| Bytes | Number of Kbytes loaded. |
| Unloaded | Number of classes unloaded. |
| Bytes | Number of Kbytes unloaded. |
| Time | Time spent performing class load and unload operations. |
jstat -gc 2083 2000 20(每隔2秒監(jiān)控一次,共做10)
輸出內(nèi)容含義如下:
| S0C | Current survivor space 0 capacity (KB). |
| EC | Current eden space capacity (KB). |
| EU | Eden space utilization (KB). |
| OC | Current old space capacity (KB). |
| OU | Old space utilization (KB). |
| PC | Current permanent space capacity (KB). |
| PU | Permanent space utilization (KB). |
| YGC | Number of young generation GC Events. |
| YGCT | Young generation garbage collection time. |
| FGC | Number of full GC events. |
| FGCT | Full garbage collection time. |
| GCT | Total garbage collection time. |
輸出內(nèi)容:
如果能熟練運(yùn)用這些命令,尤其是在linux下,那么完全可以代替jprofile等監(jiān)控工具了,誰讓它收費(fèi)呢。呵呵。
用命令的好處就是速度快,并且輔助于其他命令,比如grep gawk sed等,可以組裝多種符合自己需求的工具。
u??????????????jps的用法
用來查看JVM里面所有進(jìn)程的具體狀態(tài),?包括進(jìn)程ID,進(jìn)程啟動(dòng)的路徑等等。與unix上的ps類似,用來顯示本地的java進(jìn)程,可以查看本地運(yùn)行著幾個(gè)java程序,并顯示他們的進(jìn)程號(hào)。
?
[root@localhost ~]# jps
25517 Jps
25444 Bootstrap
?
u??????????????jstack的用法
如果java程序崩潰生成core文件,jstack工具可以用來獲得core文件的java stack和native stack的信息,從而可以輕松地知道java程序是如何崩潰和在程序何處發(fā)生問題。另外,jstack工具還可以附屬到正在運(yùn)行的java程序中,看到當(dāng)時(shí)運(yùn)行的java程序的java stack和native stack的信息,?如果現(xiàn)在運(yùn)行的java程序呈現(xiàn)hung的狀態(tài),jstack是非常有用的。目前只有在Solaris和Linux的JDK版本里面才有。
?
[root@localhost bin]# jstack?25444
Attaching to process ID 25917, please wait...
Debugger attached successfully.
Client compiler detected.
JVM version is 1.5.0_08-b03
Thread 25964: (state = BLOCKED)
Error occurred during stack walking:
sun.jvm.hotspot.debugger.DebuggerException: sun.jvm.hotspot.debugger.DebuggerException: get_thread_regs failed for a lwp
????????at sun.jvm.hotspot.debugger.linux.LinuxDebuggerLocal$LinuxDebuggerLocalWorkerThread.execute(LinuxDebuggerLocal.java:134)
????????at sun.jvm.hotspot.debugger.linux.LinuxDebuggerLocal.getThreadIntegerRegisterSet(LinuxDebuggerLocal.java:437)
????????at sun.jvm.hotspot.debugger.linux.LinuxThread.getContext(LinuxThread.java:48)
????????at sun.jvm.hotspot.runtime.linux_x86.LinuxX86JavaThreadPDAccess.getCurrentFrameGuess(LinuxX86JavaThreadPDAccess.java:75)
????????at sun.jvm.hotspot.runtime.JavaThread.getCurrentFrameGuess(JavaThread.java:252)
????????at sun.jvm.hotspot.runtime.JavaThread.getLastJavaVFrameDbg(JavaThread.java:211)
????????at sun.jvm.hotspot.tools.StackTrace.run(StackTrace.java:50)
????????at sun.jvm.hotspot.tools.JStack.run(JStack.java:41)
????????at sun.jvm.hotspot.tools.Tool.start(Tool.java:204)
????????at sun.jvm.hotspot.tools.JStack.main(JStack.java:58)
Caused by: sun.jvm.hotspot.debugger.DebuggerException: get_thread_regs failed for a lwp
????????at sun.jvm.hotspot.debugger.linux.LinuxDebuggerLocal.getThreadIntegerRegisterSet0(Native Method)
????????at sun.jvm.hotspot.debugger.linux.LinuxDebuggerLocal.access$800(LinuxDebuggerLocal.java:34)
????????at sun.jvm.hotspot.debugger.linux.LinuxDebuggerLocal$1GetThreadIntegerRegisterSetTask.doit(LinuxDebuggerLocal.java:431)
????????at sun.jvm.hotspot.debugger.linux.LinuxDebuggerLocal$LinuxDebuggerLocalWorkerThread.run(LinuxDebuggerLocal.java:109)
?
?
Thread 25963: (state = IN_NATIVE)
Error occurred during stack walking:
sun.jvm.hotspot.debugger.DebuggerException: sun.jvm.hotspot.debugger.DebuggerException: get_thread_regs failed for a lwp
????????at sun.jvm.hotspot.debugger.linux.LinuxDebuggerLocal$LinuxDebuggerLocalWorkerThread.execute(LinuxDebuggerLocal.java:134)
????????at sun.jvm.hotspot.debugger.linux.LinuxDebuggerLocal.getThreadIntegerRegisterSet(LinuxDebuggerLocal.java:437)
????????at sun.jvm.hotspot.debugger.linux.LinuxThread.getContext(LinuxThread.java:48)
????????at sun.jvm.hotspot.runtime.linux_x86.LinuxX86JavaThreadPDAccess.getCurrentFrameGuess(LinuxX86JavaThreadPDAccess.java:75)
????????at sun.jvm.hotspot.runtime.JavaThread.getCurrentFrameGuess(JavaThread.java:252)
????????at sun.jvm.hotspot.runtime.JavaThread.getLastJavaVFrameDbg(JavaThread.java:211)
????????at sun.jvm.hotspot.tools.StackTrace.run(StackTrace.java:50)
????????at sun.jvm.hotspot.tools.JStack.run(JStack.java:41)
????????at sun.jvm.hotspot.tools.Tool.start(Tool.java:204)
????????at sun.jvm.hotspot.tools.JStack.main(JStack.java:58)
Caused by: sun.jvm.hotspot.debugger.DebuggerException: get_thread_regs failed for a lwp
????????at sun.jvm.hotspot.debugger.linux.LinuxDebuggerLocal.getThreadIntegerRegisterSet0(Native Method)
????????at sun.jvm.hotspot.debugger.linux.LinuxDebuggerLocal.access$800(LinuxDebuggerLocal.java:34)
????????at sun.jvm.hotspot.debugger.linux.LinuxDebuggerLocal$1GetThreadIntegerRegisterSetTask.doit(LinuxDebuggerLocal.java:431)
????????at sun.jvm.hotspot.debugger.linux.LinuxDebuggerLocal$LinuxDebuggerLocalWorkerThread.run(LinuxDebuggerLocal.java:109)
u??????????????jstat的用法
用以判斷JVM是否存在內(nèi)存問題呢?如何判斷JVM垃圾回收是否正常?一般的top指令基本上滿足不了這樣的需求,因?yàn)樗饕O(jiān)控的是總體的系統(tǒng)資源,很難定位到java應(yīng)用程序。
Jstat是JDK自帶的一個(gè)輕量級(jí)小工具。全稱“Java Virtual Machine statistics monitoring tool”,它位于java的bin目錄下,主要利用JVM內(nèi)建的指令對(duì)Java應(yīng)用程序的資源和性能進(jìn)行實(shí)時(shí)的命令行的監(jiān)控,包括了對(duì)Heap size和垃圾回收狀況的監(jiān)控。可見,Jstat是輕量級(jí)的、專門針對(duì)JVM的工具,非常適用。由于JVM內(nèi)存設(shè)置較大,圖中百分比變化不太明顯
一個(gè)極強(qiáng)的監(jiān)視VM內(nèi)存工具。可以用來監(jiān)視VM內(nèi)存內(nèi)的各種堆和非堆的大小及其內(nèi)存使用量。
jstat工具特別強(qiáng)大,有眾多的可選項(xiàng),詳細(xì)查看堆內(nèi)各個(gè)部分的使用量,以及加載類的數(shù)量。使用時(shí),需加上查看進(jìn)程的進(jìn)程id,和所選參數(shù)。
?
?
語法結(jié)構(gòu):
Usage: jstat -help|-options
???????jstat -<option> [-t] [-h<lines>] <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ù)次
?
S0? — Heap上的?Survivor space 0?區(qū)已使用空間的百分比
S1? — Heap上的?Survivor space 1?區(qū)已使用空間的百分比
E?? — Heap上的?Eden space?區(qū)已使用空間的百分比
O?? — Heap上的?Old space?區(qū)已使用空間的百分比
P?? — Perm space?區(qū)已使用空間的百分比
YGC —?從應(yīng)用程序啟動(dòng)到采樣時(shí)發(fā)生?Young GC?的次數(shù)
YGCT–?從應(yīng)用程序啟動(dòng)到采樣時(shí)?Young GC?所用的時(shí)間(單位秒)
FGC —?從應(yīng)用程序啟動(dòng)到采樣時(shí)發(fā)生?Full GC?的次數(shù)
FGCT–?從應(yīng)用程序啟動(dòng)到采樣時(shí)?Full GC?所用的時(shí)間(單位秒)
GCT —?從應(yīng)用程序啟動(dòng)到采樣時(shí)用于垃圾回收的總時(shí)間(單位秒)
?
實(shí)例使用1:
[root@localhost bin]# jstat -gcutil 25444
??S0?????S1?????E??????O??????P?????YGC?????YGCT????FGC????FGCT?????GCT
?11.63???0.00???56.46??66.92??98.49 162????0.248????6??????0.331????0.579
?
實(shí)例使用2:
[root@localhost bin]# jstat -gcutil 25444 1000 5
??S0?????S1?????E??????O??????P?????YGC?????YGCT????FGC????FGCT?????GCT
?73.54???0.00??99.04??67.52??98.49????166????0.252?????6????0.331????0.583
?73.54???0.00??99.04??67.52??98.49????166????0.252?????6????0.331????0.583
?73.54???0.00??99.04??67.52??98.49????166????0.252?????6????0.331????0.583
?73.54???0.00??99.04??67.52??98.49????166????0.252?????6????0.331????0.583
?73.54???0.00??99.04??67.52??98.49????166????0.252?????6????0.331????0.583
總結(jié)
以上是生活随笔為你收集整理的JVM监控工具介绍jstack, jconsole, jinfo, jmap, jdb, jstat的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 使用 Java 配置进行 Spring
- 下一篇: JVM 调优参数详解