1. 程式人生 > >JVM效能監控與故障處理工具

JVM效能監控與故障處理工具

一、JVM引數

1、引數分類

  • 1.標準引數  功能和輸出的引數都是很穩定的 在未來的JVM版本中不會改變 可以使用java -help檢索出所有的標準引數
  • 2.X引數  非標準化引數 在未來的版本可能會改變 所有的引數都用-X開始 可以使用java -X檢索 但是注意沒有-Xcomp
  • 3.XX引數  非標準 很長一段時間不會列出來 用於JVM開發的debug和調優

2、SunJDK監控和故障處理工具

名稱

主要作用
jps jvm process status tool,顯示指定系統內所有的hotspot虛擬機器程序
jstat jvm statistics monitoring tool,用於收集hotspot虛擬機器各方面的執行資料
jinfo configuration info for java,顯示虛擬機器配置資訊
jmap memory map for java,生成虛擬機器的記憶體轉儲快照(heapdump檔案)
jhat jvm heap dump browser,用於分析heapmap檔案,它會建立一個http/html伺服器讓使用者可以在瀏覽器上檢視分析結果
jstack stack trace for java ,顯示虛擬機器的執行緒快照

jps

JVM Process Status Tool,顯示指定系統內所有的HotSpot虛擬機器程序。

命令格式

  jps [options] [hostid]

option引數

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

  • -q : 只輸出LVMID

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

  • -v : 輸出JVM啟動時顯示指定的JVM引數

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

示例

  $ jps -l -m
    28920 org.apache.catalina.startup.Bootstrap start
    11589 org.apache.catalina.startup.Bootstrap start
    25816 sun.tools.jps.Jps -l -m

jstat

jstat(JVM statistics Monitoring)是用於監視虛擬機器執行時狀態資訊的命令,它可以顯示出虛擬機器程序中的類裝載、記憶體、垃圾收集、JIT編譯等執行資料。

命令格式

  jstat [option] LVMID [interval] [count]

引數

  • [option] : 操作引數

  • LVMID : 本地虛擬機器程序ID

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

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

option 引數總覽

Option Displays…
class class loader的行為統計。Statistics on the behavior of the class loader.
compiler HotSpt JIT編譯器行為統計。Statistics of the behavior of the HotSpot Just-in-Time compiler.
gc 垃圾回收堆的行為統計。Statistics of the behavior of the garbage collected heap.
gccapacity 各個垃圾回收代容量(young,old,perm)和他們相應的空間統計。Statistics of the capacities of the generations and their corresponding spaces.
gcutil 垃圾回收統計概述。Summary of garbage collection statistics.
gccause 垃圾收集統計概述(同-gcutil),附加最近兩次垃圾回收事件的原因。Summary of garbage collection statistics (same as -gcutil), with the cause of the last and
gcnew 新生代行為統計。Statistics of the behavior of the new generation.
gcnewcapacity 新生代與其相應的記憶體空間的統計。Statistics of the sizes of the new generations and its corresponding spaces.
gcold 年老代和永生代行為統計。Statistics of the behavior of the old and permanent generations.
gcoldcapacity 年老代行為統計。Statistics of the sizes of the old generation.
gcpermcapacity 永生代行為統計。Statistics of the sizes of the permanent generation.
printcompilation HotSpot編譯方法統計。HotSpot compilation method statistics.

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 1262
   S0C    S1C     S0U     S1U   EC       EU        OC         OU        PC       PU         YGC    YGCT    FGC    FGCT     GCT   
  26112.0 24064.0 6562.5  0.0   564224.0 76274.5   434176.0   388518.3  524288.0 42724.7    320    6.417   1      0.398    6.815

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

  • S0C : survivor0區的總容量

  • S1C : survivor1區的總容量

  • S0U : survivor0區已使用的容量

  • S1U : survivor1區已使用的容量

  • EC : Eden區的總容量

  • EU : Eden區已使用的容量

  • OC : Old區的總容量

  • OU : Old區已使用的容量PC 當前perm的容量 (KB) PU perm的使用 (KB)

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

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

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

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

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

  $ jstat -gc 1262 2000 20

這個命令意思就是每隔2000ms輸出1262的gc情況,一共輸出20次

-gccapacity

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

  $ jstat -gccapacity 1262
   NGCMN    NGCMX     NGC    S0C   S1C       EC         OGCMN      OGCMX      OGC        OC       PGCMN    PGCMX     PGC      PC         YGC    FGC 
  614400.0 614400.0 614400.0 26112.0 24064.0 564224.0   434176.0   434176.0   434176.0   434176.0 524288.0 1048576.0 524288.0 524288.0    320     1  
  • NGCMN : 新生代佔用的最小空間

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

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

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

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

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

  • PGCMN : perm佔用的最小空間

  • PGCMX : perm佔用的最大空間

-gcutil

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

  $ jstat -gcutil 28920
    S0     S1     E      O      P     YGC     YGCT    FGC    FGCT     GCT   
   12.45   0.00  33.85   0.00   4.44  4       0.242     0    0.000    0.242

-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
    NGCMN      NGCMX       NGC      S0CMX     S0C     S1CMX     S1C       ECMX        EC        YGC   FGC 
   4194304.0  4194304.0  4194304.0 419392.0 419392.0 419392.0 419392.0  3355520.0  3355520.0     4     0
  • NGC:當前年輕代的容量 (KB)

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

  • S0C:當前S0空間 (KB)

  • ECMX:最大eden空間 (KB)

  • EC:當前eden空間 (KB)

-gcold

統計舊生代的行為

  $ jstat -gcold 28920
     PC       PU        OC           OU       YGC    FGC    FGCT     GCT   
  1048576.0  46561.7   6291456.0     0.0      4      0      0.000    0.242

-gcoldcapacity

統計舊生代的大小和空間

  $ jstat -gcoldcapacity 28920
     OGCMN       OGCMX        OGC         OC         YGC   FGC    FGCT     GCT   
    6291456.0   6291456.0   6291456.0   6291456.0     4     0    0.000    0.242

-gcpermcapacity

永生代行為統計

  $ jstat -gcpermcapacity 28920
      PGCMN      PGCMX       PGC         PC      YGC   FGC    FGCT     GCT   
   1048576.0  2097152.0  1048576.0  1048576.0     4     0    0.000    0.242

-printcompilation

hotspot編譯方法統計

  $ jstat -printcompilation 28920
      Compiled  Size  Type Method
      1291      78     1    java/util/ArrayList indexOf
  • Compiled:被執行的編譯任務的數量

  • Size:方法位元組碼的位元組數

  • Type:編譯型別

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

jmap

jmap(JVM Memory Map)命令用於生成heap dump檔案,如果不使用這個命令,還闊以使用-XX:+HeapDumpOnOutOfMemoryError引數來讓虛擬機器出現OOM的時候·自動生成dump檔案。 jmap不僅能生成dump檔案,還闊以查詢finalize執行佇列、Java堆和永久代的詳細資訊,如當前使用率、當前使用的是哪種收集器等。

命令格式

  jmap [option] LVMID

option引數

  • dump : 生成堆轉儲快照

  • finalizerinfo : 顯示在F-Queue佇列等待Finalizer執行緒執行finalizer方法的物件

  • heap : 顯示Java堆詳細資訊

  • histo : 顯示堆中物件的統計資訊

  • permstat : to print permanent generation statistics

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

示例

-dump

常用格式

  -dump::live,format=b,file=<filename> pid 

dump堆到檔案,format指定輸出格式,live指明是活著的物件,file指定檔名

  $ jmap -dump:live,format=b,file=dump.hprof 28920
    Dumping heap to /home/xxx/dump.hprof ...
    Heap dump file created

dump.hprof這個字尾是為了後續可以直接用MAT(Memory Anlysis Tool)開啟。

-finalizerinfo

列印等待回收物件的資訊

  $ 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方法的物件。

-heap

列印heap的概要資訊,GC使用的演算法,heap的配置及wise heap的使用情況,可以用此來判斷記憶體目前的使用情況以及垃圾回收情況

  $ 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.

可以很清楚的看到Java堆中各個區域目前的情況。

-histo

列印堆的物件統計,包括物件數、記憶體大小等等 (因為在dump:live前會進行full gc,如果帶上live則只統計活物件,因此不加live的堆大小要大於加live堆的大小 )

  $ jmap -histo:live 28920 | more
   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
    ....

僅僅列印了前10行

xml class name是物件型別,說明如下:

  B  byte
  C  char
  D  double
  F  float
  I  int
  J  long
  Z  boolean
  [  陣列,如[I表示int[]
  [L+類名 其他物件

-permstat

列印Java堆記憶體的永久儲存區域的類載入器的智慧統計資訊。對於每個類載入器而言,它的名稱、活躍度、地址、父類載入器、它所載入的類的數量和大小都會被列印。此外,包含的字串數量和大小也會被列印。

  $ jmap -permstat 28920
    Attaching to process ID 28920, please wait...
    Debugger attached successfully.
    Server compiler detected.
    JVM version is 24.71-b01
    finding class loader instances ..done.
    computing per loader stat ..done.
    please wait.. computing liveness.liveness analysis may be inaccurate ...
    
    class_loader            classes bytes   parent_loader           alive?  type  
    <bootstrap>             3111    18154296          null          live    <internal>
    0x0000000600905cf8      1       1888    0x0000000600087f08      dead    sun/reflect/[email protected]
    0x00000006008fcb48      1       1888    0x0000000600087f08      dead    sun/reflect/[email protected]
    0x00000006016db798      0       0       0x00000006008d3fc0      dead    java/util/[email protected]
    0x00000006008d6810      1       3056      null          dead    sun/reflect/[email protected]

-F

強制模式。如果指定的pid沒有響應,請使用jmap -dump或jmap -histo選項。此模式下,不支援live子選項。

jhat

jhat(JVM Heap Analysis Tool)命令是與jmap搭配使用,用來分析jmap生成的dump,jhat內建了一個微型的HTTP/HTML伺服器,生成dump的分析結果後,可以在瀏覽器中檢視。在此要注意,一般不會直接在伺服器上進行分析,因為jhat是一個耗時並且耗費硬體資源的過程,一般把伺服器生成的dump檔案複製到本地或其他機器上進行分析。

命令格式

  jhat [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 -J-Xmx512m dump.hprof
    eading from dump.hprof...
    Dump file created Fri Mar 11 17:13:42 CST 2016
    Snapshot read, resolving...
    Resolving 271678 objects...
    Chasing references, expect 54 dots......................................................
    Eliminating duplicate references......................................................
    Snapshot resolved.
    Started HTTP server on port 7000
    Server is ready.

中間的-J-Xmx512m是在dump快照很大的情況下分配512M記憶體去啟動HTTP伺服器,執行完之後就可在瀏覽器開啟Http://localhost:7000進行快照分析 堆快照分析主要在最後面的Heap Histogram裡,裡面根據class列出了dump的時候所有存活物件。

分析同樣一個dump快照,MAT需要的額外記憶體比jhat要小的多的多,所以建議使用MAT來進行分析,當然也看個人偏好。

分析

  All classes including platform
  Show all members of the rootset
  Show instance counts for all classes (including platform)
  Show instance counts for all classes (excluding platform)
  Show heap histogram
  Show finalizer summary
  Execute Object Query Language (OQL) query

一般檢視堆異常情況主要看這個兩個部分: Show instance counts for all classes (excluding platform),平臺外的所有物件資訊。如下圖:Show heap histogram 以樹狀圖形式展示堆情況。如下圖:具體排查時需要結合程式碼,觀察是否大量應該被回收的物件在一直被引用或者是否有佔用記憶體特別大的物件無法被回收。一般情況,會down到客戶端用工具來分析

jstack

jstack用於生成java虛擬機器當前時刻的執行緒快照。執行緒快照是當前java虛擬機器內每一條執行緒正在執行的方法堆疊的集合,生成執行緒快照的主要目的是定位執行緒出現長時間停頓的原因,如執行緒間死鎖、死迴圈、請求外部資源導致的長時間等待等。 執行緒出現停頓的時候通過jstack來檢視各個執行緒的呼叫堆疊,就可以知道沒有響應的執行緒到底在後臺做什麼事情,或者等待什麼資源。 如果java程式崩潰生成core檔案,jstack工具可以用來獲得core檔案的java stack和native stack的資訊,從而可以輕鬆地知道java程式是如何崩潰和在程式何處發生問題。另外,jstack工具還可以附屬到正在執行的java程式中,看到當時執行的java程式的java stack和native stack的資訊, 如果現在執行的java程式呈現hung的狀態,jstack是非常有用的。

命令格式

  jstack [option] LVMID

option引數

  • -F : 當正常輸出請求不被響應時,強制輸出執行緒堆疊

  • -l : 除堆疊外,顯示關於鎖的附加資訊

  • -m : 如果呼叫到本地方法的話,可以顯示C/C++的堆疊

示例

  $ jstack -l 11494|more
  2016-07-28 13:40:04
  Full thread dump Java HotSpot(TM) 64-Bit Server VM (24.71-b01 mixed mode):
  ​
  "Attach Listener" daemon prio=10 tid=0x00007febb0002000 nid=0x6b6f waiting on condition [0x0000000000000000]
     java.lang.Thread.State: RUNNABLE
  ​
     Locked ownable synchronizers:
          - None
  ​
  "http-bio-8005-exec-2" daemon prio=10 tid=0x00007feb94028000 nid=0x7b8c waiting on condition [0x00007fea8f56e000]
     java.lang.Thread.State: WAITING (parking)
          at sun.misc.Unsafe.park(Native Method)
          - parking to wait for  <0x00000000cae09b80> (a java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject)
          at java.util.concurrent.locks.LockSupport.park(LockSupport.java:186)
          at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:2043)
          at java.util.concurrent.LinkedBlockingQueue.take(LinkedBlockingQueue.java:442)
          at org.apache.tomcat.util.threads.TaskQueue.take(TaskQueue.java:104)
          at org.apache.tomcat.util.threads.TaskQueue.take(TaskQueue.java:32)
          at java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1068)
          at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1130)
          at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
          at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
          at java.lang.Thread.run(Thread.java:745)
  ​
     Locked ownable synchronizers:
          - None
        .....

分析

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

三、JDK的視覺化工具

jconsole

Jconsole(Java Monitoring and Management Console)是從java5開始,在JDK中自帶的java監控和管理控制檯,用於對JVM中記憶體,執行緒和類等的監控,是一個基於JMX(java management extensions)的GUI效能監測工具。jconsole使用jvm的擴充套件機制獲取並展示虛擬機器中執行的應用程式的效能和資源消耗等資訊。

直接在jdk/bin目錄下點選jconsole.exe即可啟動,介面如下:

在彈出的框中可以選擇本機的監控本機的java應用,也可以選擇遠端的java服務來監控,如果監控遠端服務需要在tomcat啟動指令碼中新增如下程式碼:

   -Dcom.sun.management.jmxremote.port=6969  
   -Dcom.sun.management.jmxremote.ssl=false  
   -Dcom.sun.management.jmxremote.authenticate=false

連線進去之後,就可以看到jconsole概覽圖和主要的功能:概述、記憶體、執行緒、類、VM、MBeans

  • 概述,以圖表的方式顯示出堆記憶體使用量,活動執行緒數,已載入的類,CUP佔用率的折線圖,可以非常清晰的觀察在程式執行過程中的變動情況。

  • 記憶體,主要展示了記憶體的使用情況,同時可以檢視堆和非堆記憶體的變化值對比,也可以點選執行GC來處罰GC的執行

  • 執行緒,主介面展示執行緒數的活動數和峰值,同時點選左下方執行緒可以檢視執行緒的詳細資訊,比如執行緒的狀態是什麼,堆疊內容等,同時也可以點選“檢測死鎖”來檢查執行緒之間是否有死鎖的情況。

  • 類,主要展示已載入類的相關資訊。

  • VM 概要,展示JVM所有資訊總覽,包括基本資訊、執行緒相關、堆相關、作業系統、VM引數等。

  • Mbean,檢視Mbean的屬性,方法等。

VisualVM

簡介

VisualVM 是一個工具,它提供了一個可視介面,用於檢視 Java 虛擬機器 (Java Virtual Machine, JVM) 上執行的基於 Java 技術的應用程式(Java 應用程式)的詳細資訊。VisualVM 對 Java Development Kit (JDK) 工具所檢索的 JVM 軟體相關資料進行組織,並通過一種使您可以快速檢視有關多個 Java 應用程式的資料的方式提供該資訊。您可以檢視本地應用程式以及遠端主機上執行的應用程式的相關資料。此外,還可以捕獲有關 JVM 軟體例項的資料,並將該資料儲存到本地系統,以供後期檢視或與其他使用者共享。

VisualVM 是javajdk自帶的最牛逼的調優工具了吧,也是我平時使用最多調優工具,幾乎涉及了jvm調優的方方面面。同樣是在jdk/bin目錄下面雙擊jvisualvm.exe既可使用,啟動起來後和jconsole 一樣同樣可以選擇本地和遠端,如果需要監控遠端同樣需要配置相關引數,主介面如下;

VisualVM可以根據需要安裝不同的外掛,每個外掛的關注點都不同,有的主要監控GC,有的主要監控記憶體,有的監控執行緒等。

如何安裝:

1、從主選單中選擇“工具”>“外掛”。2、在“可用外掛”標籤中,選中該外掛的“安裝”複選框。單擊“安裝”。3、逐步完成外掛安裝程式。

我這裡以 Eclipse(pid 22296)為例,雙擊後直接展開,主介面展示了系統和jvm兩大塊內容,點選右下方jvm引數和系統屬性可以參考詳細的引數資訊.

因為VisualVM的外掛太多,我這裡主要介紹三個我主要使用幾個:監控、執行緒、Visual GC

監控的主頁其實也就是,cpu、記憶體、類、執行緒的圖表

執行緒和jconsole功能沒有太大的區別

Visual GC 是常常使用的一個功能,可以明顯的看到年輕代、老年代的記憶體變化,以及gc頻率、gc的時間等。

以上的功能其實jconsole幾乎也有,VisualVM更全面更直觀一些,另外VisualVM非常多的其它功能,可以分析dump的記憶體快照,dump出來的執行緒快照並且進行分析等,還有其它很多的外掛大家可以去探索

四、其他工具

MAT

MAT是什麼?

MAT(Memory Analyzer Tool),一個基於Eclipse的記憶體分析工具,是一個快速、功能豐富的Java heap分析工具,它可以幫助我們查詢記憶體洩漏和減少記憶體消耗。使用記憶體分析工具從眾多的物件中進行分析,快速的計算出在記憶體中物件的佔用大小,看看是誰阻止了垃圾收集器的回收工作,並可以通過報表直觀的檢視到可能造成這種結果的物件。

通常記憶體洩露分析被認為是一件很有難度的工作,一般由團隊中的資深人士進行。不過要介紹的 MAT(Eclipse Memory Analyzer)被認為是一個“傻瓜式“的堆轉儲檔案分析工具,你只需要輕輕點選一下滑鼠就可以生成一個專業的分析報告。和其他記憶體洩露分析工具相比,MAT 的使用非常容易,基本可以實現一鍵到位,即使是新手也能夠很快上手使用。

MAT以eclipse 外掛的形式來安裝,具體的安裝過程就不在描述了,可以利用visualvm或者是 jmap命令生產堆檔案,匯入eclipse mat中生成分析報告:

生產這會報表的同時也會在dump檔案的同級目錄下生成三份(dump_Top_Consumers.zip、dump_Leak_Suspects.zip、dump_Top_Components.zip)分析結果的html檔案,方便傳送給相關同事來檢視。

需要關注的是下面的Actions、Reports、Step by Step區域:

  • Histogram:列出記憶體中的物件,物件的個數以及大小,支援正則表示式查詢,也可以計算出該類所有物件的retained size

  • Dominator Tree:列出最大的物件以及其依賴存活的Object (大小是以Retained Heap為標準排序的)

  • Top Consumers : 通過圖形列出最大的object

  • duplicate classes :檢測由多個類裝載器載入的類

  • Leak Suspects :記憶體洩漏分析

  • Top Components: 列出大於總堆數的百分之1的報表。

  • Component Report:分析物件屬於同一個包或者被同一個類載入器載入

以上只是一個初級的介紹,mat還有更強大的使用,比如對比堆記憶體,在生產環境中往往為了定位問題,每隔幾分鐘dump出一下記憶體快照,隨後在對比不同時間的堆記憶體的變化來發現問題。

Btrace

BTrace 中的B表示bytecode,它是在位元組碼層面上對程式碼進行trace ,通過在執行中的java類中注入trace程式碼, 並對執行中的目標程式進行熱交換(hotswap)來達到對程式碼的跟蹤 。

有兩種執行指令碼方式

  • 在JVisualVM中新增Btrace外掛,新增classpath

  • 使用命令列btrace <pid> <trace_script>

使用詳解

  1. btrace需要引入三個jar,就是下載的btrace程式中,build目錄下的三個

  1. 引入jar包

  <!--btrace -->
  ​
           <dependency>
  ​
               <groupId>com.sun.btrace</groupId>
  ​
               <artifactId>btrace-boot</artifactId>
  ​
               <version>1.3.11</version>
  ​
               <type>jar</type>
  ​
               <scope>system</scope>
  ​
               <systemPath>D:\btrace-bin-1.3.11\build\btrace-boot.jar</systemPath>
  ​
           </dependency>
  ​
  <dependency>
  ​
               <groupId>com.sun.btrace</groupId>
  ​
               <artifactId>btrace-agent</artifactId>
  ​
               <version>1.3.11</version>
  ​
               <type>jar</type>
  ​
               <scope>system</scope>
  ​
               <systemPath>D:\btrace-bin-1.3.11\build\btrace-agent.jar</systemPath>
  ​
           </dependency>
  ​
           <dependency>
  ​
               <groupId>com.sun.btrace</groupId>
  ​
               <artifactId>btrace-client</artifactId>
  ​
               <version>1.3.11</version>
  ​
               <type>jar</type>
  ​
               <scope>system</scope>
  ​
               <systemPath>D:\btrace-bin-1.3.11\build\btrace-client.jar</systemPath>
  ​
           </dependency>
  1. 將要被攔截的程式碼

import org.springframework.web.bind.annotation.RequestMapping;
  ​
  import org.springframework.web.bind.annotation.RequestParam;
  ​
  import org.springframework.web.bind.annotation.RestController;
  ​
  ​
   @RestController
  ​
   @RequestMapping("ch4")
  ​
   public class Ch4Controller {
  ​
       @RequestMapping("/arg1")
  ​
       public String arg1(@RequestParam("name")String name){
  ​
           return "hello," + name;
  ​
       }
  ​
   }
  1. btrace指令碼(指令碼和程式碼沒有必要關聯性,指令碼可以隨便寫在哪裡,沒有必要寫在方法的一個專案裡面)

package com.monitor_tuning.chapter4;
  ​
  import com.sun.btrace.AnyType;
  ​
  import com.sun.btrace.BTraceUtils;
  ​
  import com.sun.btrace.annotations.*;
  ​
  @BTrace
  ​
   public class PrintArgSimple {
  ​
       @OnMethod(
  ​
               clazz = "com.monitor_tuning.chapter4.Ch4Controller",
  ​
               method = "arg1",
  ​
               location = @Location(Kind.ENTRY)
  ​
       )
  ​
       public static void anyRead(@ProbeClassName String pcn, @ProbeMethodName String pmn, AnyType[] args){
  ​
           BTraceUtils.printArray(args);
  ​
           BTraceUtils.println(pcn + "," + pmn);
  ​
           BTraceUtils.println();
  ​
       }
  ​
   }

@OnMethod表示我們要攔截哪個類的哪個方法,在什麼時候進行攔截

Kind.ENTRY表示在入口的時候攔截(也就是一進入方法的時候)

@param pcn 攔截方法類的類名

@param pmn 攔截方法的方法名

@param args 引數

  • 進入到btrace指令碼的目錄下

  • 檢視程序id

  • 執行指令碼檔案

  • Java VisualVM開啟btrace

注意事項

1.預設只能本地執行

2.生產環境下可以使用,但是被修改的位元組碼不會被還原(即使btrace退出)

因此,指令碼中不要有太耗系統資源的東西,否則會影響伺服器。

參考資料:

《深入理解Java虛擬機器:JVM高階特性與最佳實踐》第二版