JAVA虛擬機之六:虛擬機性能監控和故障處理工具

一、JDK命令行工具簡介
所有的java開發人員都知道JDK的bin目錄下存放着編譯java需要的javac,以及運行java程序需要的java這兩個命令工具,但是很多人並沒有注意到,其實除了這兩個工具,該目錄下還有很多工具,這些工具其實爲我們提供了很多方便且強大的功能,windows7系統64位jdk1.7/bin目錄下部分截圖:
下面是命令行監控的主要工具和用途:
名稱     作用
jps JVM Process Status Tool,現實指定系統內所有的HotSpot虛擬機進程 
jstat JVM Statistics Monitoring Tool,用於收集Hotspot虛擬機各個方面的運行參數 
jinfo Configuration Info for Java,現實虛擬機配置信息
jmap Memory map for java,生成虛擬機的內存轉儲快照
jhat JVM heap Dunp Browser,用於分析heapdump文件,他會建立一個HTTP/HTML服務,讓用戶可通過瀏覽器查看 
jstack Stack Track for java ,顯示虛擬機線程快照
1、jps
    jps用來查看基於HotSpot的JVM裏面中,所有具有訪問權限的Java進程的具體狀態, 包括進程ID,進程啓動的路徑及啓動參數等等,與unix上的ps類似,只不過jps是用來顯示java進程,可以把jps理解爲ps的一個子集。 使用jps時,如果沒有指定hostid,它只會顯示本地環境中所有的Java進程;如果指定了hostid,它就會顯示指定hostid上面的java進程,不過這需要遠程服務上開啓了jstatd服務,可以參看前面的jstatd章節來啓動jstad服務。
命令格式 :jps [ options ] [ hostid ] 
參數說明 :
-q 忽略輸出的類名、Jar名以及傳遞給main方法的參數,只輸出pid。
-m 輸出傳遞給main方法的參數,如果是內嵌的JVM則輸出爲null。
-l 輸出應用程序主類的完整包名,或者是應用程序JAR文件的完整路徑。
-v 輸出傳給JVM的參數。
-V 輸出通過標記的文件傳遞給JVM的參數(.hotspotrc文件,或者是通過參數-XX:Flags=<filename>指定的文件)。
-J 用於傳遞jvm選項到由javac調用的java加載器中,例如,“-J-Xms48m”將把啓動內存設置爲48M,使用-J選項可以非常方便的向基於Java的開發的底層虛擬機應用程序傳遞參數。下面樣例均在linux的jdk1.7下測試。
使用樣例:
[root@tools138 ~]# jps
2897 Bootstrap
22558 Jps
[root@tools138 ~]# jps -l
2897 org.apache.catalina.startup.Bootstrap
22568 sun.tools.jps.Jps
[root@tools138 ~]# jps -v
2897 Bootstrap -Djava.util.logging.config.file=/usr/local/tomcat/conf/logging.properties -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager -Djava.endorsed.dirs=/usr/local/tomcat/endorsed -Dcatalina.base=/usr/local/tomcat -Dcatalina.home=/usr/local/tomcat -Djava.io.tmpdir=/usr/local/tomcat/temp
22578 Jps -Denv.class.path=/usr/java/jdk1.7.0/lib -Dapplication.home=/usr/java/jdk1.7.0 -Xms8m
 
2、jstat

Jstat用於監控基於HotSpot的JVM,對其堆的使用情況進行實時的命令行的統計,使用jstat我們可以對指定的JVM做如下監控:

- 類的加載及卸載情況

- 查看新生代、老生代及持久代的容量及使用情況

- 查看新生代、老生代及持久代的垃圾收集情況,包括垃圾回收的次數及垃圾回收所佔用的時間

- 查看新生代中Eden區及Survior區中容量及分配情況等

jstat工具特別強大,它有衆多的可選項,通過提供多種不同的監控維度,使我們可以從不同的維度來瞭解到當前JVM堆的使用情況。詳細查看堆內各個部分的使用量,使用的時候必須加上待統計的Java進程號,可選的不同維度參數以及可選的統計頻率參數。

命令格式:

jstat [ option vmid [interval][s|ms][count]]

option 參數如下面表格

Option Displays...
class 用於查看類加載情況的統計
compiler 用於查看HotSpot中即時編譯器編譯情況的統計
gc 用於查看JVM中堆的垃圾收集情況的統計
gccapacity 用於查看新生代、老生代及持久代的存儲容量情況
gccause 用於查看垃圾收集的統計情況(這個和-gcutil選項一樣),如果有發生垃圾收集,它還會顯示最後一次及當前正在發生垃圾收集的原因。
gcnew 用於查看新生代垃圾收集的情況
gcnewcapacity 用於查看新生代的存儲容量情況
gcold 用於查看老生代及持久代發生GC的情況
gcoldcapacity 用於查看老生代的容量
gcpermcapacity 用於查看持久代的容量
gcutil 用於查看新生代、老生代及持代垃圾收集的情況
printcompilation HotSpot編譯方法的統計
interval 和count 代表查詢次數和間隔。
使用樣例:
[root@tools138 ~]# jstat -class 2897
Loaded  Bytes  Unloaded  Bytes     Time  
 67431 113866.2    59850 98607.5    1884.07
 
[root@tools138 ~]# jstat -compiler  2897
Compiled Failed Invalid   Time   FailedType FailedMethod
    3782      1       0   507.88          1 org/apache/tomcat/util/IntrospectionUtils setProperty

 表示查詢系統進程爲2897的java程序gc,每100毫秒查詢一次,一共查詢十次,顯示結果每列的含義如下: 
列名 說明
S0C 新生代中Survivor space中S0當前容量的大小(KB)
S1C 新生代中Survivor space中S1當前容量的大小(KB)
S0U 新生代中Survivor space中S0容量使用的大小(KB)
S1U 新生代中Survivor space中S1容量使用的大小(KB)
EC Eden space當前容量的大小(KB)
EU Eden space容量使用的大小(KB)
OC Old space當前容量的大小(KB)
OU Old space使用容量的大小(KB)
PC Permanent space當前容量的大小(KB)
PU Permanent space使用容量的大小(KB)
YGC 從應用程序啓動到採樣時發生 Young GC 的次數
YGCT 從應用程序啓動到採樣時 Young GC 所用的時間(秒)
FGC 從應用程序啓動到採樣時發生 Full GC 的次數
FGCT 從應用程序啓動到採樣時 Full GC 所用的時間(秒)
GCT T從應用程序啓動到採樣時用於垃圾回收的總時間(單位秒),它的值等於YGC+FGC
其他以gc開始的結果列跟gc選項結果列基本一樣,這裏不一一列舉了。
 
3、jinfo
jinfo可以輸出並修改運行時的java 進程的opts。用處比較簡單,用於輸出JAVA系統參數及命令行參數。
命令格式:
jinfo [option] pid
使用樣例:
[root@tools138 ~]# jinfo  -flag  MaxNewSize  2897
-XX:MaxNewSize=18446744073709486080
 
4、jmap
jmap用於生成堆轉儲快照(一般稱爲heapdump或者dump文件)。當然也可其他方法比如加參數-XX:+HeapDumpOnOutOfMemoryError參數,在虛擬機OOM異常的之後自動生成dump文件,也可以通過-XX:+HeapDumpOnCtrlBreak參數則可以使用Ctrl+Break鍵讓虛擬機生成dump文件。在前文《 JAVA虛擬機之3:CMS垃圾收集器》測試中就有生成。dump文件生成後可藉助jha、MAT( Eclipse Memory Analyzer tool)、IBM HeapAnalyzer來對dump分析。jmap不僅能獲取dump還可以查詢finalize執行隊列,java堆和永久代詳細信息,空間使用率,當前用的是什麼收集器等。
jmap -J-d64 -heap pid
命令格式:
       jmap [ option ] pid
參數說明:
-dump:[live,]format=b,file=<filename> 使用hprof二進制形式,輸出jvm的heap內容到文件=. live子選項是可選的,假如指定live選項,那麼只輸出活的對象到文件.
-finalizerinfo 打印正等候回收的對象的信息.
-heap 打印heap的概要信息,GC使用的算法,heap的配置及wise heap的使用情況.
-histo[:live] 打印每個class的實例數目,內存佔用,類全名信息. VM的內部類名字開頭會加上前綴”*”. 如果live子參數加上後,只統計活的對象數量.
-permstat 打印classload和jvm heap長久層的信息. 包含每個classloader的名字,活潑性,地址,父classloader和加載的class數量. 另外,內部String的數量和佔用內存數也會打印出來.
-F 強迫.在pid沒有相應的時候使用-dump或者-histo參數. 在這個模式下,live子參數無效.
使用樣例:
jmap -dump:format=b,file=eclipse.bin
[root@tools138 ~]# jmap -dump:format=b,file=eclipse.bin  2897
Dumping heap to /root/eclipse.bin ...
Heap dump file created
 
5、jhat
jhat是sun提供的dump分析工具,上面講過分析dump的工具還有MAT( Eclipse Memory Analyzer tool)、IBM HeapAnalyzer等,一般這個命令不太用到,是因爲分析dump是個既耗時又耗機器資源的過程,第二個原因是這個工具比較簡陋,沒有MAT( Eclipse Memory Analyzer tool)、IBM HeapAnalyzer這些專業和強大。
命令格式:
jhat file
使用樣例:
防止影響服務,所以在本地windows下使用,先導出dump文件
C:\Users\hz>jmap -dump:format=b,file=test.bin 5152
Dumping heap to C:\Users\hz\test.bin ...
Heap dump file created
然後分析:
C:\Users\hz>jhat test.bin
Reading from test.bin...
Dump file created Wed Dec 30 13:29:19 CST 2015
Snapshot read, resolving...
Resolving 9692 objects...
Chasing references, expect 1 dots.
Eliminating duplicate references.
Snapshot resolved.
Started HTTP server on port 7000
Server is ready.
載在瀏覽器中輸入localhost:7000查看結果,如下圖。

 
6、jstack
jstack用於打印出給定的java進程ID或core file或遠程調試服務的Java堆棧信息,如果是在64位機器上,需要指定選項"-J-d64",Windows的jstack使用方式只支持以下的這種方式:
如果java程序崩潰生成core文件,jstack工具可以用來獲得core文件的java stack和native stack的信息,從而可以輕鬆地知道java程序是如何崩潰和在程序何處發生問題。另外,jstack工具還可以附屬到正在運行的java程序中,看到當時運行的java程序的java stack和native stack的信息, 如果現在運行的java程序呈現hung的狀態,jstack是非常有用的。 
命令格式 :
jstack [ option ] pid
參數說明:
-F當’jstack [-l] pid’沒有相應的時候強制打印棧信息
-l長列表. 打印關於鎖的附加信息,例如屬於java.util.concurrent的ownable synchronizers列表.
-m打印java和native c/c++框架的所有棧信息.
使用樣例:
[root@tts217 ~]# jstack -l 29984
.....
 
"main" prio=10 tid=0x00007fe648009000 nid=0x7521 runnable [0x00007fe64e753000]
   java.lang.Thread.State: RUNNABLE
 at java.net.PlainSocketImpl.socketAccept(Native Method)
 at java.net.AbstractPlainSocketImpl.accept(AbstractPlainSocketImpl.java:398)
 at java.net.ServerSocket.implAccept(ServerSocket.java:530)
 at java.net.ServerSocket.accept(ServerSocket.java:498)
 at org.apache.catalina.core.StandardServer.await(StandardServer.java:453)
 at org.apache.catalina.startup.Catalina.await(Catalina.java:777)
 at org.apache.catalina.startup.Catalina.start(Catalina.java:723)
 at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
 at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
 at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
 at java.lang.reflect.Method.invoke(Method.java:606)
 at org.apache.catalina.startup.Bootstrap.start(Bootstrap.java:321)
 at org.apache.catalina.startup.Bootstrap.main(Bootstrap.java:455)
 
   Locked ownable synchronizers:
 - None
 
"VM Thread" prio=10 tid=0x00007fe64806a800 nid=0x7522 runnable
 
"VM Periodic Task Thread" prio=10 tid=0x00007fe6480a5800 nid=0x7529 waiting on condition
 
JNI global references: 238
 
二、JDK可視化工具
1、jconsole
JConsole是一個基於JMX的GUI工具,用於連接正在運行的JVM,不過此JVM需要使用可管理的模式啓動。如果要把一個應用以可管理的形式啓動,可以在啓動是設置com.sun.management.jmxremote。
jconsole可以選擇本地連接,來查看本地java程序參數,也可以連接遠程機器來使用,下面連接本地看:


a、概述:有關堆內存使用情況、線程、類加載和CPU使用情況的綜述。如下圖所示:

 b、內存:堆內存和其他內存。如下圖所示:

 c、線程:峯值/活動線程,在此頁面可以查看到各個線程的明細,也可以進行死鎖檢測。如下圖所示:

 d、類:監控加載和卸載的類,這個需要綜合其他工具進行具體的分析。
e、VM摘要:有關JVM的明細信息。
f、Mbean:當前Java程序的Mbean的操作。
在jconsole裏主要可以用來監控內存和線程監控,內存監控相當於jstat,曲線可以選擇

 可以手動執行gc。線程監控可用來檢測死鎖。
死鎖代碼如下:
package jvm;
/**
 * 描述:
 *
 * @author alaric 2016年1月1日 上午12:43:23
 */
public class A implements Runnable {
 int a, b;
 public A(int a, int b) {
  this.a = a;
  this.b = b;
 }
 /*
  * (non-Javadoc)
  *
  * @see java.lang.Runnable#run()
  */
 @Override
 public void run() {
  // 描述
  synchronized (Integer.valueOf(a)) {
   synchronized (Integer.valueOf(b)) {
    System.out.println(" a + b = " + (a + b));
   }
  }
 }
 public static void main(String[] args) {
  for (int i = 0; i < 100; i++) {
   new Thread(new A(1, 2)).start();
   new Thread(new A(2, 1)).start();
  }
 }
}
多運行幾次會出現死鎖,程序會阻塞。然後用線程監控,點擊檢測死鎖,發現Thread-199和Thread-198相互等待釋放Integer.value(1)或者Integer.value(2)。因爲在200次的代碼執行中Integer.value()就返回了兩個對象。



 
2、jvisualVM
jvisualVM所謂多合一虛擬機故障處理工具,有強大的插件擴展功能,通過安裝插件擴展支持,jvisualVM可以做到:
a、顯示虛擬機進程及進程的配置和環境信息(jps,jinfo);
b、監視應用程序CPU、GC、堆、方法區及線程的信息(jstat、jstack);
c、dump及分析堆轉儲快照(jmap、jhat);
d、方法級的程序性能分析,找出調用最多,運行時間最長的方法;
.....其它通過插件可以做到的;
概述裏面可以看到虛擬機版本及配置的參數等。
 在監視裏可以看cpu、堆、線程類的相關數據。可以執行垃圾回收和dump堆。
 在線程裏可以看到所有線程,包括運行的、休眠的、等待的、駐留的等,包括運行時間。同時可以dump線程。

 在抽樣器中可以監控到每個方法執行的時間,還可以對方法過濾。點擊線程cpu時間,可以看到每個線程cpu時間。

 VisualGC這裏可以看到虛擬機運行時每個區域的容量大小,已佔用的大小,youngGC和fullGC的次數,以及編譯時間、類加載數量和加載時間等。

 
三、總結:
jdk提供的vm故障處理工具都比較實用,常用的jps,jstat,jmap,jstack以及可視化工具visualvm,當然根據個人實際實用情況,可能還選用第三方的工具進行dump分析,如eclipse的MAT(Memory Analyzer Tool)等。靈活實用這些工具,可以給處理問題帶來很大的便利。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章