JDK的命令行工具(jps,jmap,jstat,jstack...)的介紹和使用

當你的程序出現例如堆棧溢出,程序崩潰等問題,往往可以通過Jvm的自帶命令行工具來進行排查。

本文主要介紹內容:

Jcmd:綜合工具

jps:虛擬機進程狀況工具

jstat:虛擬機統計信息監視工具

jinfo:Java配置信息工具

jmap:Java內存映像工具

jhat:虛擬機堆轉儲快照分析工具

jstack:Java堆棧跟蹤工


轉載自:https://www.cnblogs.com/wade-luffy/p/6017137.html

 Jcmd:綜合工具

jcmd -l  列出當前運行的所有虛擬機

參數-l表示列出所有java虛擬機,針對每一個虛擬機,可以使用help命令列出該虛擬機支持的所有命令

jcmd [pid] help

jcmd [pid] VM.uptime   查看虛擬機啓動時間VM.uptime

jcmd [pid] Thread.print  打印線程棧信息Thread.print

jcmd 21024 GC.class_histogram  查看系統中類統計信息GC.class_histogram

jcmd [pid] GC.heap_dump [filepath&name]  導出堆信息GC.heap_dump  這個命令功能和 jmap -dump 功能一樣

jcmd [pid] VM.system_properties 獲取系統Properties內容VM.system_properties

jcmd [pid] VM.flags 獲取啓動參數VM.flags

jcmd [pid] PerfCounter.print  獲取所有性能相關數據PerfCounter.print

jps:虛擬機進程狀況工具

jps(JVM Process Status Tool)可以列出正在運行的虛擬機進程,並顯示虛擬機執行主類(Main Class,main()函數所在的類)名稱以及這些進程的本地虛擬機唯一ID(Local Virtual Machine Identifier,LVMID)。雖然功能比較單一,但它是使用頻率最高的JDK命令行工具,因爲其他的JDK工具大多需要輸入它查詢到的LVMID來確定要監控的是哪一個虛擬機進程。對於本地虛擬機進程來說,LVMID與操作系統的進程ID(Process Identifier,PID)是一致的,使用Windows的任務管理器或者UNIX的ps命令也可以查詢到虛擬機進程的LVMID,但如果同時啓動了多個虛擬機進程,無法根據進程名稱定位時,那就只能依賴jps命令顯示主類的功能才能區分了。

命令格式

 jps [options] [hostid]

option參數

  • -l : 輸出主類全名或jar路徑

  • -q : 只輸出LVMID

  • -m : 輸出JVM啓動時傳遞給main()的參數

  • -v : 輸出JVM啓動時顯示指定的JVM參數

其中[option]、[hostid]參數也可以不寫。

回到頂部

jinfo

jinfo(JVM Configuration info)這個命令作用是實時查看和調整虛擬機運行參數。 之前的jps -v口令只能查看到顯示指定的參數,如果想要查看未被顯示指定的參數的值就要使用jinfo口令 

命令格式

jinfo [option] [args] LVMID

option參數

  • -flag : 輸出指定args參數的值

  • -flags : 不需要args參數,輸出所有JVM參數的值

  • -sysprops : 輸出系統屬性,等同於System.getProperties()

示例

$ jinfo -flag 11494

-XX:CMSInitiatingOccupancyFraction=80

jstat:虛擬機統計信息監視工具

jstat(JVM statistics Monitoring)是用於監視虛擬機運行時狀態信息的命令,它可以顯示出虛擬機進程中的類裝載、內存、垃圾收集、JIT編譯等運行數據。

命令格式

 jstat [option] LVMID [interval] [count]

參數

  • [option] : 操作參數

  • LVMID : 本地虛擬機進程ID

  • [interval] : 連續輸出的時間間隔

  • [count] : 連續輸出的次數

對於命令格式中的VMID與LVMID需要特別說明一下:

如果是本地虛擬機進程,VMID與LVMID是一致的;

如果是遠程虛擬機進程,那VMID的格式應當是:protocol://lvmid@hostname:port/servername

參數interval和count代表查詢間隔(單位毫秒)和次數,如果省略這兩個參數,說明只查詢一次。

假設需要每250毫秒查詢一次進程2764垃圾收集狀況,一共查詢20次,那命令應當是:jstat -gc 2764 250 20

選項option代表着用戶希望查詢的虛擬機信息,主要分爲3類:類裝載、垃圾收集、運行期編譯狀況,具體選項及作用請參考表4-3中的描述。

option 參數詳解

-class

監視類裝載、卸載數量、總空間以及耗費的時間

$ jstat -class 11589

 Loaded  Bytes  Unloaded  Bytes     Time   

  7035  14506.3     0     0.0       3.67

  • Loaded : 加載class的數量

  • Bytes : class字節大小

  • Unloaded : 未加載class的數量

  • Bytes : 未加載class的字節大小

  • Time : 加載時間

-compiler

輸出JIT編譯過的方法數量耗時等

$ jstat -compiler 1262

Compiled Failed Invalid   Time   FailedType FailedMethod

2573      1       0    47.60          1               org/apache/catalina/loader/WebappClassLoader findResourceInternal

  • Compiled : 編譯數量

  • Failed : 編譯失敗數量

  • Invalid : 無效數量

  • Time : 編譯耗時

  • FailedType : 失敗類型

  • FailedMethod : 失敗方法的全限定名

-gc

垃圾回收堆的行爲統計,常用命令jstat -gc 2764 250 20

S0   S1     E    O    P    YGC  YGCT   FGC  FGCT   GCT

0.00  0.00   6.20  41.42  47.20  16   0.105   3    0.472   0.577

查詢結果表明:這臺服務器的新生代Eden區(E,表示Eden)使用了6.2%的空間,兩個Survivor區(S0、S1,表示Survivor0、Survivor1)裏面都是空的,老年代(O,表示Old)和永久代(P,表示Permanent)則分別使用了41.42%和47.20%的空間。程序運行以來共發生Minor GC(YGC,表示Young GC)16次,總耗時0.105秒,發生Full GC(FGC,表示Full GC)3次,Full GC總耗時(FGCT,表示Full GC Time)爲0.472秒,所有GC總耗時(GCT,表示GC Time)爲0.577秒。

C即Capacity 總容量,U即Used 已使用的容量

  • S0C : survivor0區的總容量

  • S1C : survivor1區的總容量

  • S0U : survivor0區已使用的容量

  • S1C : survivor1區已使用的容量

  • EC : Eden區的總容量

  • EU : Eden區已使用的容量

  • OC : Old區的總容量

  • OU : Old區已使用的容量

  • PC 當前perm的容量 (KB)

  • PU perm的使用 (KB)

  • YGC : 新生代垃圾回收次數

  • YGCT : 新生代垃圾回收時間

  • FGC : 老年代垃圾回收次數

  • FGCT : 老年代垃圾回收時間

  • GCT : 垃圾回收總消耗時間

-gccapacity

同-gc,不過還會輸出Java堆各區域使用到的最大、最小空間

$ jstat -gccapacity 1262

  • NGCMN : 新生代佔用的最小空間

  • NGCMX : 新生代佔用的最大空間

  • OGCMN : 老年代佔用的最小空間

  • OGCMX : 老年代佔用的最大空間

  • OGC:當前年老代的容量 (KB)

  • OC:當前年老代的空間 (KB)

  • PGCMN : perm佔用的最小空間

  • PGCMX : perm佔用的最大空間

-gcutil

同-gc,不過輸出的是已使用空間佔總空間的百分比

-gccause

垃圾收集統計概述(同-gcutil),附加最近兩次垃圾回收事件的原因

$ jstat -gccause 28920

 S0     S1     E      O      P       YGC     YGCT    FGC    FGCT     GCT       LGCC                 GCC                 

 12.45   0.00  33.85   0.00   4.44      4    0.242     0    0.000    0.242   Allocation Failure   No GC

  • LGCC:最近垃圾回收的原因

  • GCC:當前垃圾回收的原因

-gcnew

統計新生代的行爲

$ jstat -gcnew 28920

 S0C      S1C      S0U        S1U  TT  MTT  DSS      EC        EU         YGC     YGCT  

 419392.0 419392.0 52231.8    0.0  6   6    209696.0 3355520.0 1172246.0  4       0.242

  • TT:Tenuring threshold(提升閾值)

  • MTT:最大的tenuring threshold

  • DSS:survivor區域大小 (KB)

-gcnewcapacity

新生代與其相應的內存空間的統計

$ jstat -gcnewcapacity 28920

  • NGC:當前年輕代的容量 (KB)

  • S0CMX:最大的S0空間 (KB)

  • S0C:當前S0空間 (KB)

  • ECMX:最大eden空間 (KB)

  • EC:當前eden空間 (KB)

-gcold

統計舊生代的行爲

 $ jstat -gcold 28920

-gcoldcapacity

統計舊生代的大小和空間

$ jstat -gcoldcapacity 28920

-gcpermcapacity

永生代行爲統計

 $ jstat -gcpermcapacity 28920

-printcompilation

hotspot編譯方法統計

 $ jstat -printcompilation 28920

    Compiled  Size  Type Method

    1291      78     1    java/util/ArrayList indexOf

  • Compiled:被執行的編譯任務的數量

  • Size:方法字節碼的字節數

  • Type:編譯類型

  • Method:編譯方法的類名和方法名。類名使用”/” 代替 “.” 作爲空間分隔符. 方法名是給出類的方法名. 格式是一致於HotSpot – XX:+PrintComplation 選項

jinfo:Java配置信息工具

jinfo(Configuration Info for Java)的作用是實時地查看和調整虛擬機各項參數。使用jps命令的-v參數可以查看虛擬機啓動時顯式指定的參數列表,但如果想知道未被顯式指定的參數的系統默認值,除了去找資料外,就只能使用jinfo的-flag選項進行查詢了(如果只限於JDK 1.6或以上版本的話,使用java-XX:+PrintFlagsFinal查看參數默認值也是一個很好的選擇),jinfo還可以使用-sysprops選項把虛擬機進程的System.getProperties()的內容打印出來。這個命令在JDK 1.5時期已經隨着Linux版的JDK發佈,當時只提供了信息查詢的功能,JDK 1.6之後,jinfo在Windows和Linux平臺都有提供,並且加入了運行期修改參數的能力,可以使用-flag[+|-]name或者-flag name=value修改一部分運行期可寫的虛擬機參數值。JDK 1.6中,jinfo對於Windows平臺功能仍然有較大限制,只提供了最基本的-flag選項。

jinfo命令格式:

jinfo option pid

執行樣例:查詢CMSInitiatingOccupancyFraction參數值。

C:\>jinfo-flag CMSInitiatingOccupancyFraction 1444

-XX:CMSInitiatingOccupancyFraction=85

jmap:Java內存映像工具

jmap(Memory Map for Java)命令用於生成堆轉儲快照(一般稱爲heapdump或dump文件)。

如果不使用jmap命令,要想獲取Java堆轉儲快照,還有一些比較“暴力”的手段:譬如加-XX:+HeapDumpOnOutOfMemoryError參數,可以讓虛擬機在OOM異常出現之後自動生成dump文件,通過-XX:+HeapDumpOnCtrlBreak參數則可以使用[Ctrl]+[Break]鍵讓虛擬機生成dump文件,又或者在Linux系統下通過Kill-3命令發送進程退出信號“嚇唬”一下虛擬機,也能拿到dump文件。

jmap的作用並不僅僅是爲了獲取dump文件,它還可以查詢finalize執行隊列、Java堆和永久代的詳細信息,如空間使用率、當前用的是哪種收集器等。和jinfo命令一樣,jmap有不少功能在Windows平臺下都是受限的,除了生成dump文件的-dump選項和用於查看每個類的實例、空間佔用統計的-histo選項在所有操作系統都提供之外,其餘選項都只能在Linux/Solaris下使用。

命令格式

 jmap [option] LVMID

option參數

  • dump : 生成堆轉儲快照,格式爲:-dump:[live, ] format=b,file=<filename>,其中live子參數說明是否只dump出存活的對象。

  • finalizerinfo : 顯示在F-Queue隊列等待Finalizer線程執行finalizer方法的對象

  • heap : 顯示Java堆詳細信息

  • histo : 顯示堆中對象的統計信息,GC使用的算法,heap的配置及wise heap的使用情況,可以用此來判斷內存目前的使用情況以及垃圾回收情況

  • permstat : to print permanent generation statistics

  • F : 當-dump沒有響應時,強制生成dump快照

示例:

jmap -dump:format=b,file=eclipse.bin 40195 

jmap -dump:live,format=b,file=dump.hprof 28920     dump.hprof這個後綴是爲了後續可以直接用MAT(Memory Anlysis Tool)打開。

 

jmap -finalizerinfo 28920   打印等待回收對象的信息

  Attaching to process ID 28920, please wait...

  Debugger attached successfully.

  Server compiler detected.

  JVM version is 24.71-b01

  Number of objects pending for finalization: 0

可以看到當前F-QUEUE隊列中並沒有等待Finalizer線程執行finalizer方法的對象。

jmap -heap 28920

Attaching to process ID 28920, please wait...

  Debugger attached successfully.
  Server compiler detected.
  JVM version is 24.71-b01  
  using thread-local object allocation.
  Parallel GC with 4 thread(s)//GC 方式  
  Heap Configuration: //堆內存初始化配置
     MinHeapFreeRatio = 0 //對應jvm啓動參數-XX:MinHeapFreeRatio設置JVM堆最小空閒比率(default 40)
     MaxHeapFreeRatio = 100 //對應jvm啓動參數 -XX:MaxHeapFreeRatio設置JVM堆最大空閒比率(default 70)
     MaxHeapSize      = 2082471936 (1986.0MB) //對應jvm啓動參數-XX:MaxHeapSize=設置JVM堆的最大大小
     NewSize          = 1310720 (1.25MB)//對應jvm啓動參數-XX:NewSize=設置JVM堆的‘新生代’的默認大小
     MaxNewSize       = 17592186044415 MB//對應jvm啓動參數-XX:MaxNewSize=設置JVM堆的‘新生代’的最大大小
     OldSize          = 5439488 (5.1875MB)//對應jvm啓動參數-XX:OldSize=<value>:設置JVM堆的‘老生代’的大小
     NewRatio         = 2 //對應jvm啓動參數-XX:NewRatio=:‘新生代’和‘老生代’的大小比率
     SurvivorRatio    = 8 //對應jvm啓動參數-XX:SurvivorRatio=設置年輕代中Eden區與Survivor區的大小比值 
     PermSize         = 21757952 (20.75MB)  //對應jvm啓動參數-XX:PermSize=<value>:設置JVM堆的‘永生代’的初始大小
     MaxPermSize      = 85983232 (82.0MB)//對應jvm啓動參數-XX:MaxPermSize=<value>:設置JVM堆的‘永生代’的最大大小
     G1HeapRegionSize = 0 (0.0MB)  
  Heap Usage://堆內存使用情況
  PS Young Generation
  Eden Space://Eden區內存分佈
     capacity = 33030144 (31.5MB)//Eden區總容量
     used     = 1524040 (1.4534378051757812MB)  //Eden區已使用
     free     = 31506104 (30.04656219482422MB)  //Eden區剩餘容量
     4.614088270399305% used //Eden區使用比率
  From Space:  //其中一個Survivor區的內存分佈
     capacity = 5242880 (5.0MB)
     used     = 0 (0.0MB)
     free     = 5242880 (5.0MB)
     0.0% used
  To Space:  //另一個Survivor區的內存分佈
     capacity = 5242880 (5.0MB)
     used     = 0 (0.0MB)
     free     = 5242880 (5.0MB)
     0.0% used
  PS Old Generation //當前的Old區內存分佈
     capacity = 86507520 (82.5MB)
     used     = 0 (0.0MB)
     free     = 86507520 (82.5MB)
     0.0% used
  PS Perm Generation//當前的 “永生代” 內存分佈
     capacity = 22020096 (21.0MB)
     used     = 2496528 (2.3808746337890625MB)
     free     = 19523568 (18.619125366210938MB)
     11.337498256138392% used  
  670 interned Strings occupying 43720 bytes.

 

jmap -histo:live 28920 | more

打印堆的對象統計,包括對象數、內存大小等等 (因爲在dump:live前會進行full gc,如果帶上live則只統計活對象,因此不加live的堆大小要大於加live堆的大小 )

 

num     #instances         #bytes  class name
----------------------------------------------
   1:         83613       12012248  <constMethodKlass>
   2:         23868       11450280  [B
   3:         83613       10716064  <methodKlass>
   4:         76287       10412128  [C
   5:          8227        9021176  <constantPoolKlass>
   6:          8227        5830256  <instanceKlassKlass>
   7:          7031        5156480  <constantPoolCacheKlass>
   8:         73627        1767048  java.lang.String
   9:          2260        1348848  <methodDataKlass>
  10:          8856         849296  java.lang.Class

xml class name是對象類型,說明如下:

B  byte
C  char
D  double
F  float
I  int
J  long
Z  boolean
[  數組,如[I表示int[]
[L+類名 其他對象

jhat:虛擬機堆轉儲快照分析工具

jhat(JVM Heap Analysis Tool)命令與jmap搭配使用,來分析jmap生成的堆轉儲快照。jhat內置了一個微型的HTTP/HTML服務器,生成dump文件的分析結果後,可以在瀏覽器中查看。

不過實事求是地說,在實際工作中,除非手上真的沒有別的工具可用,否則一般都不會去直接使用jhat命令來分析dump文件,主要原因有二:一是一般不會在部署應用程序的服務器上直接分析dump文件,即使可以這樣做,也會盡量將dump文件複製到其他機器。二是用於分析的機器一般也是服務器,由於加載dump快照文件需要比生成dump更大的內存,所以一般在64位JDK、大內存的服務器上進行分析,因爲分析工作是一個耗時而且消耗硬件資源的過程,既然都要在其他機器進行,就沒有必要受到命令行工具的限制了;另一個原因是jhat的分析功能相對來說比較簡陋,VisualVM,以及專業用於分析dump文件的Eclipse Memory Analyzer、IBM HeapAnalyzer等工具,都能實現比jhat更強大更專業的分析功能。

命令格式

 jhat [option] [dumpfile]

參數

  • -stack false|true 關閉對象分配調用棧跟蹤(tracking object allocation call stack)。 如果分配位置信息在堆轉儲中不可用. 則必須將此標誌設置爲 false. 默認值爲 true.>

  • -refs false|true 關閉對象引用跟蹤(tracking of references to objects)。 默認值爲 true. 默認情況下, 返回的指針是指向其他特定對象的對象,如反向鏈接或輸入引用(referrers or incoming references), 會統計/計算堆中的所有對象。>

  • -port port-number 設置 jhat HTTP server 的端口號. 默認值 7000.> 

  • -exclude exclude-file 指定對象查詢時需要排除的數據成員列表文件(a file that lists data members that should be excluded from the reachable objects query)。 例如, 如果文件列列出了 java.lang.String.value , 那麼當從某個特定對象 Object o 計算可達的對象列表時, 引用路徑涉及 java.lang.String.value 的都會被排除。>

  • -baseline exclude-file 指定一個基準堆轉儲(baseline heap dump)。 在兩個 heap dumps 中有相同 object ID 的對象會被標記爲不是新的(marked as not being new). 其他對象被標記爲新的(new). 在比較兩個不同的堆轉儲時很有用.>

  • -debug int 設置 debug 級別. 0 表示不輸出調試信息。 值越大則表示輸出更詳細的 debug 信息.>

  • -version 啓動後只顯示版本信息就退出>

  • -J< flag > 因爲 jhat 命令實際上會啓動一個JVM來執行, 通過 -J 可以在啓動JVM時傳入一些啓動參數. 例如, -J-Xmx512m 則指定運行 jhat 的Java虛擬機使用的最大堆內存爲 512 MB. 如果需要使用多個JVM啓動參數,則傳入多個 -Jxxxxxx. 

  • ➜  ~jhat eclipse.bin 

Reading from eclipse.bin...

Dump file created Mon Oct 31 19:32:57 CST 2016

Snapshot read, resolving...

Resolving 185857 objects...

Chasing references, expect 37 dots.....................................

Eliminating duplicate references.....................................

Snapshot resolved.

Started HTTP server on port 7000

Server is ready.

屏幕顯示“Server is ready.”的提示後,用戶在瀏覽器中鍵入http://localhost:7000/就可以看到分析結果.

分析結果默認是以包爲單位進行分組顯示,分析內存泄漏問題主要會使用到其中的“Heap Histogram”(與jmap -histo功能一樣)與OQL頁籤的功能,前者可以找到內存中總容量最大的對象,後者是標準的對象查詢語言,使用類似SQL的語法對內存中的對象進行查詢統計.

jstack:Java堆棧跟蹤工具

jstack(Stack Trace for Java)命令用於生成虛擬機當前時刻的線程快照(一般稱爲threaddump或者javacore文件)。線程快照就是當前虛擬機內每一條線程正在執行的方法堆棧的集合,生成線程快照的主要目的是定位線程出現長時間停頓的原因,如線程間死鎖、死循環、請求外部資源導致的長時間等待等都是導致線程長時間停頓的常見原因。線程出現停頓的時候通過jstack來查看各個線程的調用堆棧,就可以知道沒有響應的線程到底在後臺做些什麼事情,或者等待着什麼資源。

命令格式

 jstack [option] LVMID

option參數

  • -F : 當正常輸出請求不被響應時,強制輸出線程堆棧

  • -l : 除堆棧外,顯示關於鎖的附加信息

  • -m : 如果調用到本地方法的話,可以顯示C/C++的堆棧

➜  ~ jstack -l 40195

在JDK 1.5中,java.lang.Thread類新增了一個getAllStackTraces()方法用於獲取虛擬機中所有線程的StackTraceElement對象。使用這個方法可以通過簡單的幾行代碼就完成jstack的大部分功能,在實際項目中不妨調用這個方法做個管理員頁面,可以隨時使用瀏覽器來查看線程堆棧。

<%@page import="java.util.Map"%> 
<html> 
<head> 
<title>服務器線程信息</title> 
</head> 
<body> 
<pre> <% for(Map.Entry<Thread,StackTraceElement[]>stackTrace:Thread.getAllStackTraces().entrySet()){
Thread thread=(Thread)stackTrace.getKey();   
StackTraceElement[]stack=(StackTraceElement[])stackTrace.getValue();   if(thread.equals(Thread.currentThread())){     
continue;   }   
out.print("\n線程:"+thread.getName()+"\n");   
for(StackTraceElement element:stack){     
out.print("\t"+element+"\n");   } } 
%> 
</pre> 
</body> 
</html>

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章