java包中提供了很多監控JVM的工具類,作為java程序員必須得掌握常用的幾個工具,下面是幾個常用的JVM性能監控與故障處理工具的介紹與使用。
1、jstack
該命令用於生成當前時刻虛擬機的線程快照,可以用於定位線程出現長時間停頓的原因,包括死鎖、死循環、超時等待等。
jstack命令格式:
jstack [option] vmid
vmid可以通過ps -ef|grep java命令得到,第二個參數的PID值就是vmid。
option的可選值:
-F 當正常輸出的請求不被響應時,強制輸出線程堆棧
-l 除堆棧外,顯示關於鎖的附加信息
-m 如果調用到本地方法的話,可顯示C/C++的堆棧
查詢示例:
1.1 jstack -l 18614
控制台輸出的部分結果:
Full thread dump Java HotSpot(TM) Server VM (25.151-b12 mixed mode): "Attach Listener" #50 daemon prio=9 os_prio=0 tid=0xa58bd000 nid=0x6427 waiting on condition [0x00000000] java.lang.Thread.State: RUNNABLE Locked ownable synchronizers: - None "Abandoned connection cleanup thread" #49 daemon prio=5 os_prio=0 tid=0x09bc8800 nid=0x4932 in Object.wait() [0xa558c000] java.lang.Thread.State: TIMED_WAITING (on object monitor) at java.lang.Object.wait(Native Method) at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:143) - locked <0xad5b5730> (a java.lang.ref.ReferenceQueue$Lock) at com.mysql.jdbc.AbandonedConnectionCleanupThread.run(AbandonedConnectionCleanupThread.java:43) Locked ownable synchronizers: - None "Tomcat JDBC Pool Cleaner[24630847:1546674815832]" #48 daemon prio=5 os_prio=0 tid=0x096f9000 nid=0x4931 in Object.wait() [0xa55dd000] java.lang.Thread.State: TIMED_WAITING (on object monitor) at java.lang.Object.wait(Native Method) at java.util.TimerThread.mainLoop(Timer.java:552) - locked <0xad2b10d0> (a java.util.TaskQueue) at java.util.TimerThread.run(Timer.java:505) Locked ownable synchronizers: - None "ajp-nio-8009-AsyncTimeout" #46 daemon prio=5 os_prio=0 tid=0xa7eae000 nid=0x492f waiting on condition [0xa5cb8000] java.lang.Thread.State: TIMED_WAITING (sleeping) at java.lang.Thread.sleep(Native Method) at org.apache.coyote.AbstractProtocol$AsyncTimeout.run(AbstractProtocol.java:1149) at java.lang.Thread.run(Thread.java:748) Locked ownable synchronizers: - None "ajp-nio-8009-Acceptor-0" #45 daemon prio=5 os_prio=0 tid=0xa7eacc00 nid=0x492e runnable [0xa5d09000] java.lang.Thread.State: RUNNABLE at sun.nio.ch.ServerSocketChannelImpl.accept0(Native Method) at sun.nio.ch.ServerSocketChannelImpl.accept(ServerSocketChannelImpl.java:422) at sun.nio.ch.ServerSocketChannelImpl.accept(ServerSocketChannelImpl.java:250) - locked <0xac53a438> (a java.lang.Object) at org.apache.tomcat.util.net.NioEndpoint$Acceptor.run(NioEndpoint.java:482) at java.lang.Thread.run(Thread.java:748) Locked ownable synchronizers: - None
1.2 jstack -m 18614
下面的部分結果中的紅色字說明沒有死鎖發生。
Attaching to process ID 18614, please wait... Debugger attached successfully. Server compiler detected. JVM version is 25.151-b12 Deadlock Detection: No deadlocks found. ----------------- 18615 ----------------- 0xf7735430 ???????? 0xa87b2938 NET_Timeout + 0x38 0xa87aecbe Java_java_net_PlainSocketImpl_socketAccept + 0x21e 0xe74fb646 * java.net.PlainSocketImpl.socketAccept(java.net.SocketImpl) bci:0 (Interpreted frame) 0xe74f1d4a * java.net.AbstractPlainSocketImpl.accept(java.net.SocketImpl) bci:7 line:409 (Interpreted frame) 0xe74f1d4a * java.net.ServerSocket.implAccept(java.net.Socket) bci:60 line:545 (Interpreted frame) 0xe74f1d4a * java.net.ServerSocket.accept() bci:48 line:513 (Interpreted frame) 0xe74f1b54 * org.apache.catalina.core.StandardServer.await() bci:180 line:466 (Interpreted frame) 0xe74f1d7f * org.apache.catalina.startup.Catalina.await() bci:4 line:775 (Interpreted frame) 0xe74f1d4a * org.apache.catalina.startup.Catalina.start() bci:209 line:721 (Interpreted frame) 0xe74ed499 <StubRoutines> 0xf6becb3f _ZN9JavaCalls11call_helperEP9JavaValueP12methodHandleP17JavaCallArgumentsP6Thread + 0x101f 0xf6e40489 _ZN2os20os_exception_wrapperEPFvP9JavaValueP12methodHandleP17JavaCallArgumentsP6ThreadES1_S3_S5_S7_ + 0x19 0xf6beb10f _ZN9JavaCalls4callEP9JavaValue12methodHandleP17JavaCallArgumentsP6Thread + 0x2f 0xf6eb2812 _ZN10Reflection6invokeE19instanceKlassHandle12methodHandle6Handleb14objArrayHandle9BasicTypeS3_bP6Thread + 0x4d2 0xf6eb5ba8 _ZN10Reflection13invoke_methodEP7oopDesc6Handle14objArrayHandleP6Thread + 0x148 0xf6c7f4ef JVM_InvokeMethod + 0x25f 0xf6629552 Java_sun_reflect_NativeMethodAccessorImpl_invoke0 + 0x32 0xe74fb646 * sun.reflect.NativeMethodAccessorImpl.invoke0(java.lang.reflect.Method, java.lang.Object, java.lang.Object[]) bci:0 (Interpreted frame) 0xe74f1b54 * sun.reflect.NativeMethodAccessorImpl.invoke(java.lang.Object, java.lang.Object[]) bci:100 line:62 (Interpreted frame) 0xe7639144 * sun.reflect.DelegatingMethodAccessorImpl.invoke(java.lang.Object, java.lang.Object[]) bci:6 line:43 (Compiled frame) * java.lang.reflect.Method.invoke(java.lang.Object, java.lang.Object[]) bci:56 line:498 (Compiled frame) * org.apache.catalina.startup.Bootstrap.start() bci:37 line:353 (Interpreted frame) 0xe74f1d4a * org.apache.catalina.startup.Bootstrap.main(java.lang.String[]) bci:150 line:493 (Interpreted frame) 0xe74ed499 <StubRoutines> 0xf6becb3f _ZN9JavaCalls11call_helperEP9JavaValueP12methodHandleP17JavaCallArgumentsP6Thread + 0x101f 0xf6e40489 _ZN2os20os_exception_wrapperEPFvP9JavaValueP12methodHandleP17JavaCallArgumentsP6ThreadES1_S3_S5_S7_ + 0x19 0xf6beb10f _ZN9JavaCalls4callEP9JavaValue12methodHandleP17JavaCallArgumentsP6Thread + 0x2f 0xf6c35187 _ZL17jni_invoke_staticP7JNIEnv_P9JavaValueP8_jobject11JNICallTypeP10_jmethodIDP18JNI_ArgumentPusherP6Thread + 0x387 0xf6c47c0f jni_CallStaticVoidMethod + 0xdf 0xf76de8a9 JavaMain + 0x8e9 0xf76f3b2c start_thread + 0xcc ----------------- 18616 ----------------- 0xf7735430 ???????? ----------------- 18617 ----------------- 0xf7735430 ???????? ----------------- 18618 ----------------- 0xf7735430 ???????? ----------------- 18619 ----------------- 0xf7735430 ???????? ----------------- 18620 ----------------- 0xf7735430 ???????? ----------------- 18621 ----------------- 0xf7735430 ???????? sun.jvm.hotspot.debugger.UnmappedAddressException: f0 at sun.jvm.hotspot.debugger.PageCache.checkPage(PageCache.java:208) at sun.jvm.hotspot.debugger.PageCache.getData(PageCache.java:63) at sun.jvm.hotspot.debugger.DebuggerBase.readBytes(DebuggerBase.java:225) at sun.jvm.hotspot.debugger.linux.LinuxDebuggerLocal.readCInteger(LinuxDebuggerLocal.java:498) at sun.jvm.hotspot.debugger.DebuggerBase.readAddressValue(DebuggerBase.java:462) at sun.jvm.hotspot.debugger.linux.LinuxDebuggerLocal.readAddress(LinuxDebuggerLocal.java:433) at sun.jvm.hotspot.debugger.linux.LinuxAddress.getAddressAt(LinuxAddress.java:74) at sun.jvm.hotspot.debugger.linux.x86.LinuxX86CFrame.sender(LinuxX86CFrame.java:69) at sun.jvm.hotspot.tools.PStack.run(PStack.java:161) at sun.jvm.hotspot.tools.PStack.run(PStack.java:58) at sun.jvm.hotspot.tools.PStack.run(PStack.java:53) at sun.jvm.hotspot.tools.JStack.run(JStack.java:66) at sun.jvm.hotspot.tools.Tool.startInternal(Tool.java:260) at sun.jvm.hotspot.tools.Tool.start(Tool.java:223) at sun.jvm.hotspot.tools.Tool.execute(Tool.java:118) at sun.jvm.hotspot.tools.JStack.main(JStack.java:92) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:498) at sun.tools.jstack.JStack.runJStackTool(JStack.java:140) at sun.tools.jstack.JStack.main(JStack.java:106)
----------------- 18622 -----------------
0xf7735430 ????????
----------------- 18623 -----------------
0xf7735430 ????????
----------------- 18624 -----------------
0xf7735430 ????????
----------------- 18625 -----------------
0xf7735430 ????????
----------------- 18631 -----------------
0xf7735430 ????????
----------------- 18649 -----------------
0xf7735430 ????????
----------------- 18650 -----------------
0xf7735430 ????????
0xe7d9e4cb <Unknown compiled code>
0xe806cbfc * sun.nio.ch.EPollArrayWrapper.poll(long) bci:18 line:269 (Compiled frame)
* sun.nio.ch.EPollSelectorImpl.doSelect(long) bci:28 line:93 (Compiled frame)
* sun.nio.ch.SelectorImpl.lockAndDoSelect(long) bci:37 line:86 (Compiled frame)
* sun.nio.ch.SelectorImpl.select(long) bci:30 line:97 (Compiled frame)
----------------- 18651 -----------------
0xf7735430 ????????
0xe7d9e4cb <Unknown compiled code>
0xe806cbfc * sun.nio.ch.EPollArrayWrapper.poll(long) bci:18 line:269 (Compiled frame)
* sun.nio.ch.EPollSelectorImpl.doSelect(long) bci:28 line:93 (Compiled frame)
* sun.nio.ch.SelectorImpl.lockAndDoSelect(long) bci:37 line:86 (Compiled frame)
* sun.nio.ch.SelectorImpl.select(long) bci:30 line:97 (Compiled frame)
2、jstat
該命令用於監視虛擬機各種運行狀態信息,包括類裝載、內存、垃圾回收、JIT編譯等數據,是運行期定位JVM性能問題的首選工具。
jstat命令格式:
jstat [option vmid [interval[s|ms] [count]] ]
interval:查詢間隔(ms單位),count:查詢次數,若忽略這2個參數,則只查詢一次。
option為用戶需要查詢的虛擬機信息,包括類裝載、GC、運行期編譯狀態等。可選項如下:
-class 監視類裝載、卸載數量、總空間及類裝載所耗費的時間 -gc 監視java堆狀況,包括Eden區、兩個survivor區、老年代、永久代等的容量、已用空間、GC時間合計等信息 -gccapacity 監視內容與-gc基本相同,但輸出的主要關注java堆各個區域使用到的最大、最小空間 -gcutil 監視內容與-gc基本相同,但輸出的主要關注已使用空間占總空間的百分比 -gccause 與-gcutil功能一樣,但是會額外輸出上一次GC產生的原因 -gcnew 監視新生代GC狀況 -gcnewcapacity 監視內容與-gcnew基本相同,輸出主要關注使用到的最大、最小空間 -gcold 監視老年代GC狀況 -gcoldcapacity 監視內容與-gcold基本相同,輸出主要關注使用到的最大、最小空間 -gcpermcapacity 輸出永久代使用到的最大、最小空間 -compiler 輸出JIT編譯器編譯過的方法、耗時等信息 -printcompilation 輸出已被JIT編譯的方法
示例:
2.1 jstat -gc 18614 200 10 每200毫秒查詢一次進程PID為18614的垃圾收集情況,一共查詢10次。
S0C S1C S0U S1U EC EU OC OU MC MU CCSC CCSU YGC YGCT FGC FGCT GCT 33792.0 42240.0 806.7 0.0 171264.0 162460.8 61440.0 30525.4 25240.0 24905.6 0.0 0.0 24 0.338 3 0.239 0.576 33792.0 42240.0 806.7 0.0 171264.0 162460.8 61440.0 30525.4 25240.0 24905.6 0.0 0.0 24 0.338 3 0.239 0.576 33792.0 42240.0 806.7 0.0 171264.0 162460.8 61440.0 30525.4 25240.0 24905.6 0.0 0.0 24 0.338 3 0.239 0.576 33792.0 42240.0 806.7 0.0 171264.0 162460.8 61440.0 30525.4 25240.0 24905.6 0.0 0.0 24 0.338 3 0.239 0.576 33792.0 42240.0 806.7 0.0 171264.0 162460.8 61440.0 30525.4 25240.0 24905.6 0.0 0.0 24 0.338 3 0.239 0.576 33792.0 42240.0 806.7 0.0 171264.0 162460.8 61440.0 30525.4 25240.0 24905.6 0.0 0.0 24 0.338 3 0.239 0.576 33792.0 42240.0 806.7 0.0 171264.0 162460.8 61440.0 30525.4 25240.0 24905.6 0.0 0.0 24 0.338 3 0.239 0.576 33792.0 42240.0 806.7 0.0 171264.0 162460.8 61440.0 30525.4 25240.0 24905.6 0.0 0.0 24 0.338 3 0.239 0.576 33792.0 42240.0 806.7 0.0 171264.0 162460.8 61440.0 30525.4 25240.0 24905.6 0.0 0.0 24 0.338 3 0.239 0.576 33792.0 42240.0 806.7 0.0 171264.0 162460.8 61440.0 30525.4 25240.0 24905.6 0.0 0.0 24 0.338 3 0.239 0.576
查詢結果的標題列含義:
S0C:當前Survivor0區空間大小(kb);S1C:當前Survivor1區空間大小(kb)
S0U:當前Survivor0區空間使用量(kb);S1U:當前Survivor1區空間使用量(kb)
EC:當前Eden區空間大小(kb);EU:當前Eden區空間使用量(kb)
OC:當前Old區空間大小(kb);OU:當前Old區空間使用量(kb)
MC:方法區空間大小(kb);MU:方法區空間使用量(kb)
CCSC:壓縮類空間大小(kb);CCSU:壓縮類空間空間使用量(kb)
YGC:Young GC次數;YGCT:Young GC耗時
FGC:Full GC次數;FGCT:Full GC耗時
GCT:GC總耗時
2.2 jstat -gcutil 18614
S0 S1 E O M CCS YGC YGCT FGC FGCT GCT 2.39 0.00 100.00 49.68 98.68 - 24 0.338 3 0.239 0.576
說明:Survivor0區使用了2.39%的空間,Survivor1區使用了0.00%的空間,Eden區使用了100%的空間,Old區使用了49.68%的空間,方法區使用了98.68的空間。程序運行以來,Young GC發生了24次,耗時0.338秒,Full GC發生了3次,耗時0.239秒,所有GC總耗時0.576秒。
2.2 jstat -class 18614
Loaded Bytes Unloaded Bytes Time 5554 6350.0 0 0.0 7.93
說明:程序裝載了5554個類,共6350字節,卸載了0個類,共0個字節,類裝載耗時7.93秒。
2.3 jstat -gcnew 18614
S0C S1C S0U S1U TT MTT DSS EC EU YGC YGCT 41216.0 1024.0 0.0 798.2 9 15 41216.0 164096.0 5723.0 25 0.342
2.4 jstat -gcold 18614
MC MU CCSC CCSU OC OU YGC FGC FGCT GCT 25368.0 24912.1 0.0 0.0 61440.0 30525.4 25 3 0.239 0.580
2.5 jstat -compiler 18614
Compiled Failed Invalid Time FailedType FailedMethod 7018 1 0 21.29 1 com/mysql/jdbc/AbandonedConnectionCleanupThread run
說明:JIT編譯器編譯成功方法7018個,失敗1個,無效0個,耗時21.29秒,失敗類型為1,失敗的方法為AbandonedConnectionCleanupThread類的run方法。
參考:《深入理解Java虛擬機》---周志明 著