JVM性能調優監控工具解析

我們在企業級Java開發的過程中有時會遇到以下問題:

  • 內存泄漏
  • 線程死鎖
  • 鎖搶佔
  • CPU佔用過高
  • 等等

JVM提供了一些命令工具可以幫助我們來定位這些問題:

1. Jps(Java Virtual Machine Process Status Tool)

它主要用來輸出JVM中正在運行的進程狀態信息。其語法格式如下:

usage: jps [-help]
       jps [-q] [-mlvV] [<hostid>]

Definitions:
    <hostid>:      <hostname>[:<port>]

Definitions中的host如果不指定,就代表本機。

其參數說明如下:

-q只輸出進程號,不輸出類名,jar名和main方法的傳入參數。
-m輸出傳入main方法的參數。
-l輸出main類或Jar的全限定名。
-v輸出傳入JVM的參數。

2. Jstack

jstack主要用來查看某個Java進程內所有線程的堆棧信息。其語法格式如下:

Usage:
    jstack [-l] <pid>
        (to connect to running process)
    jstack -F [-m] [-l] <pid>
        (to connect to a hung process)
    jstack [-m] [-l] <executable> <core>
        (to connect to a core file)
    jstack [-m] [-l] [server_id@]<remote server IP or hostname>
        (to connect to a remote debug server)

Options:
    -F  to force a thread dump. Use when jstack <pid> does not respond (process is hung)
    -m  to print both java and native frames (mixed mode)
    -l  long listing. Prints additional information about locks
    -h or -help to print this help message

Jstack可以通過線程堆棧信息來定位到具體代碼。比如有一個線程CPU消耗特別高,如何查呢?具體方式如下:

  1. 根據linux命令:ps -ef | grep java 來查到需要定位的jvm進程號<pid>
  2. 使用linux命令:top -Hp <pid> 來查到CPU使用最高的線程號。並將該線程號轉換爲16進制。
  3. 通過jvm命令:jstack -l <pid> > aaa.log 將該JVM進程的堆棧信息寫入aaa.log文件中。
  4. 在aaa.log中查找我們算出的16進制的那個線程號。找到的堆棧信息就是該線程的堆棧信息。

3. jmap

jmap可以查看JVM中堆內存的使用情況。其使用語法如下:

Usage:
    jmap [option] <pid>
        (to connect to running process)
    jmap [option] <executable <core>
        (to connect to a core file)
    jmap [option] [server_id@]<remote server IP or hostname>
        (to connect to remote debug server)

where <option> is one of:
    <none>               to print same info as Solaris pmap
    -heap                to print java heap summary
    -histo[:live]        to print histogram of java object heap; if the "live"
                         suboption is specified, only count live objects
    -clstats             to print class loader statistics
    -finalizerinfo       to print information on objects awaiting finalization
    -dump:<dump-options> to dump java heap in hprof binary format
                         dump-options:
                           live         dump only live objects; if not specified,
                                        all objects in the heap are dumped.
                           format=b     binary format
                           file=<file>  dump heap to <file>
                         Example: jmap -dump:live,format=b,file=heap.bin <pid>
    -F                   force. Use with -dump:<dump-options> <pid> or -histo
                         to force a heap dump or histogram when <pid> does not
                         respond. The "live" suboption is not supported
                         in this mode.
    -h | -help           to print this help message
    -J<flag>             to pass <flag> directly to the runtime system
使用jmap -histo[:live] <pid> 查看堆內存中的對象數目、大小統計直方圖,如果帶上live則只統計活對象,如下所示:
172.20.120.15:hadoop@sz-pg-app-hadoop-001:/home/hadoop]$ jmap -histo:live 22651 | more

 num     #instances         #bytes  class name
----------------------------------------------
   1:         14798       37768024  [I
   2:         65877       29211512  [C
   3:          6239       13987208  [B
   4:         75269        4165384  [Ljava.lang.Object;
   5:         71952        2878080  java.lang.ref.Finalizer
   6:         56021        2240840  org.apache.commons.dbcp2.DelegatingPreparedStatement
   7:        116128        1858048  java.lang.Object
   8:         54438        1742016  java.util.HashMap$Node
   9:         69013        1656312  java.util.ArrayList
  10:         62762        1506288  java.lang.String
  11:         11865        1325728  java.lang.Class
  12:         18610        1323840  [Ljava.util.HashMap$Node;
  13:          8492        1222848  org.jboss.netty.channel.socket.nio.NioClientSocketChannel
  14:         30941         990112  java.util.concurrent.ConcurrentHashMap$Node
  15:          8675         971600  sun.nio.ch.SocketChannelImpl
  16:         17303         830544  java.util.HashMap
  17:         34456         826944  java.net.InetSocketAddress$InetSocketAddressHolder
  18:          7312         818944  java.net.SocksSocketImpl
  19:          8492         747296  org.jboss.netty.handler.codec.http.HttpClientCodec$Decoder
  20:         17008         680320  org.jboss.netty.channel.DefaultChannelPipeline$DefaultChannelHandlerContext
  21:         25518         612432  java.util.concurrent.ConcurrentLinkedQueue$Node
  22:         34456         551296  java.net.InetSocketAddress
  23:           359         499168  [Ljava.nio.ByteBuffer;
  24:          8494         475664  org.jboss.netty.util.HashedWheelTimer$HashedWheelTimeout
  25:          5111         449768  java.lang.reflect.Method
  26:         17198         412752  java.util.concurrent.ConcurrentLinkedQueue
  27:          8492         407616  org.jboss.netty.channel.AbstractChannel$ChannelCloseFuture
上面那幾個class name都是啥意思呢?

Bbyte帶符號的byte
CcharUnicode字符
Ddouble雙精度浮點數
Ffloat單精度浮點數
Iint32位整數
Jlong64位整數
Sshort16位整數
Zbooleantrue or false
LClassnamereference

引用類型

Ljava/lang/String 表示String

Ljava/lang/Integer 表示Integer

[reference

數組類型,例如

[I 表示 int[]

[Ljava/lang/Object 表示Object[]

[[[D 表示 double[][][]

4. jstat

jstat是JVM的統計監測工具。其語法格式如下:

Usage: jstat -help|-options
       jstat -<option> [-t] [-h<lines>] <vmid> [<interval> [<count>]]

Definitions:
  <option>      An option reported by the -options option
  <vmid>        Virtual Machine Identifier. A vmid takes the following form:
                     <lvmid>[@<hostname>[:<port>]]
                Where <lvmid> is the local vm identifier for the target
                Java virtual machine, typically a process id; <hostname> is
                the name of the host running the target Java virtual machine;
                and <port> is the port number for the rmiregistry on the
                target host. See the jvmstat documentation for a more complete
                description of the Virtual Machine Identifier.
  <lines>       Number of samples between header lines.
  <interval>    Sampling interval. The following forms are allowed:
                    <n>["ms"|"s"]
                Where <n> is an integer and the suffix specifies the units as 
                milliseconds("ms") or seconds("s"). The default units are "ms".
  <count>       Number of samples to take before terminating.
  -J<flag>      Pass <flag> directly to the runtime system.

其Option參數如下:

    jstat -class pid:顯示加載class的數量,及所佔空間等信息。 
    jstat -compiler pid:顯示VM實時編譯的數量等信息。 
    jstat -gc pid:可以顯示gc的信息,查看gc的次數,及時間。其中最後五項,分別是young gc的次數,young gc的時間,full gc的次數,full gc的時間,gc的總時間。 
    jstat -gccapacity:可以顯示,VM內存中三代(young,old,perm)對象的使用和佔用大小,如:PGCMN顯示的是最小perm的內存使用量,PGCMX顯示的是perm的內存最大使用量,PGC是當前新生成的perm內存佔用量,PC是但前perm內存佔用量。其他的可以根據這個類推, OC是old內純的佔用量。 
    jstat -gcnew pid:new對象的信息。 
    jstat -gcnewcapacity pid:new對象的信息及其佔用量。 
    jstat -gcold pid:old對象的信息。 
    jstat -gcoldcapacity pid:old對象的信息及其佔用量。 
    jstat -gcpermcapacity pid: perm對象的信息及其佔用量。 
    jstat -gcutil pid:統計gc信息統計。 
    jstat -printcompilation pid:當前VM執行的信息。 

舉例如下:

172.20.120.15:hadoop@sz-pg-app-hadoop-001:/home/hadoop]$ jstat -gcutil 22651 1000 1000
  S0     S1     E      O      M     CCS    YGC     YGCT    FGC    FGCT     GCT   
  0.00  63.70  72.08   4.31  97.42  96.27  72859 1655.000     6    1.480 1656.479
  0.00  63.70  72.54   4.31  97.42  96.27  72859 1655.000     6    1.480 1656.479
  0.00  63.70  72.76   4.31  97.42  96.27  72859 1655.000     6    1.480 1656.479
  0.00  63.70  73.47   4.31  97.42  96.27  72859 1655.000     6    1.480 1656.479
S0  — Heap上的 Survivor space 0 區已使用空間的百分比 
S1  — Heap上的 Survivor space 1 區已使用空間的百分比 
E   — Heap上的 Eden space 區已使用空間的百分比 
O   — Heap上的 Old space 區已使用空間的百分比 
P   — Perm space 區已使用空間的百分比 
YGC — 從應用程序啓動到採樣時發生 Young GC 的次數 
YGCT– 從應用程序啓動到採樣時 Young GC 所用的時間(單位秒) 
FGC — 從應用程序啓動到採樣時發生 Full GC 的次數 
FGCT– 從應用程序啓動到採樣時 Full GC 所用的時間(單位秒) 
GCT — 從應用程序啓動到採樣時用於垃圾回收的總時間(單位秒) 

發佈了45 篇原創文章 · 獲贊 19 · 訪問量 8萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章