JVM 之(8)虛擬機監控工具(命令)

1.jps (Java Virtual Machine Process Status Tool)  

    用來查看基於HotSpot的JVM裏面中,全部具備訪問權限的Java進程的具體狀態, 包括進程ID,進程啓動的路徑及啓動參數等等,與unix上的ps相似,只不過jps是用來顯示java進程,能夠把jps理解爲ps的一個子集。

    jps [options] [hostid]
    若是不指定hostid就默認爲當前主機或服務器;若是指定了hostid,它就會顯示指定hostid上面的java進程,不過這須要遠程服務上開啓了jstatd服務。

    -q:忽略輸出的類名、Jar名以及傳遞給main方法的參數,只輸出pid。
    -m:輸出傳遞給main方法的參數,若是是內嵌的JVM則輸出爲null。
    -l:輸出徹底的包名,應用主類名,jar的徹底路徑名
    -v:輸出傳給jvm的參數
    -V:輸出經過標記的文件傳遞給JVM的參數(.hotspotrc文件,或者是經過參數-XX:Flags=指定的文件)。
    -J 用於傳遞jvm選項到由javac調用的java加載器中,例如,「-J-Xms48m」將把啓動內存設置爲48M,使用-J選項能夠很是方便的向基於Java的開發的底層虛擬機應用程序傳遞參數。

    jps -mlv

9680 org.jetbrains.idea.maven.server.RemoteMavenServer -Djava.awt.headless=true -Didea.version==2017.1.1 -Xmx768m -Didea.maven.embedder.version=3.2.5 -Dfile.encoding=GBK
2356 org.jetbrains.jps.cmdline.Launcher C:/Program Files/JetBrains/IntelliJ IDEA 2017.1.1/lib/openapi.jar;C:/Program Files/JetBrains/IntelliJ IDEA 2017.1.1/lib/jgoodies-forms.jar;C:/Program Files/JetBrains/IntelliJ IDEA 2017.1.1/lib/javac2.jar;C:/Program Files/JetBrains/IntelliJ IDEA 2017.1.1/lib/idea_rt.jar;C:/Program Files/JetBrains/IntelliJ IDEA 2017.1.1/lib/jna-platform.jar;C:/Program Files/JetBrains/IntelliJ IDEA 2017.1.1/lib/netty-all-4.1.9.Final.jar;C:/Program Files/JetBrains/IntelliJ IDEA 2017.1.1/lib/protobuf-2.5.0.jar;C:/Program Files/JetBrains/IntelliJ IDEA 2017.1.1/lib/annotations.jar;C:/Program Files/JetBrains/IntelliJ IDEA 2017.1.1/lib/trove4j.jar;C:/Program Files/JetBrains/IntelliJ IDEA 2017.1.1/lib/nanoxml-2.2.3.jar;C:/Program Files/JetBrains/IntelliJ IDEA 2017.1.1/lib/forms_rt.jar;C:/Program Files/JetBrains/IntelliJ IDEA 2017.1.1/lib/jdom.jar;C:/Program Files/JetBrains/IntelliJ IDEA 2017.1.1/lib/asm-all.jar;C:/Program Files/JetBrains/IntelliJ IDEA 2017.1.1/lib/jps-model.jar;C:/Program Files/JetBra -Xmx700m -Djava.awt.headless=true -Djava.endorsed.dirs="" -Djdt.compiler.useSingleThread=true -Dcompile.parallel=false -Drebuild.on.dependency.change=true -Djava.net.preferIPv4Stack=true -Dio.netty.initialSeedUniquifier=-8384703316530083662 -Dfile.encoding=GBK -Djps.file.types.component.name=FileTypeManager -Duser.language=zh -Duser.country=CN -Didea.paths.selector=IntelliJIdea2017.1 -Didea.home.path=C:\Program Files\JetBrains\IntelliJ IDEA 2017.1.1 -Didea.config.path=C:\Users\vincent\.IntelliJIdea2017.1\config -Didea.plugins.path=C:\Users\vincent\.IntelliJIdea2017.1\config\plugins -Djps.log.dir=C:/Users/vincent/.IntelliJIdea2017.1/system/log/build-log -Djps.fallback.jdk.home=C:/Program Files/JetBrains/IntelliJ IDEA 2017.1.1/jre64 -Djps.fallback.jdk.version=1.8.0_112-release -Dio.netty.noUnsafe=true -Djava.io.tmpdir=C:/Users/vincent/.IntelliJIdea2017.1/system/compile-server/es-demo_7a0f3d0f/_temp_ -Djps.backward.ref.index.builder=true -Dkotlin.incremental.compilation.experimental=true -Dkotlin.daemon.enabled
4116  -Xms128m -Xmx750m -XX:ReservedCodeCacheSize=240m -XX:+UseConcMarkSweepGC -XX:SoftRefLRUPolicyMSPerMB=50 -ea -Dsun.io.useCanonCaches=false -Djava.net.preferIPv4Stack=true -XX:+HeapDumpOnOutOfMemoryError -XX:-OmitStackTraceInFastThrow -Djb.vmOptionsFile=C:\Program Files\JetBrains\IntelliJ IDEA 2017.1.1\bin\idea64.exe.vmoptions -Xbootclasspath/a:C:\Program Files\JetBrains\IntelliJ IDEA 2017.1.1\lib\boot.jar -Didea.jre.check=true -Didea.paths.selector=IntelliJIdea2017.1 -XX:ErrorFile=C:\Users\vincent\java_error_in_idea_%p.log -XX:HeapDumpPath=C:\Users\vincent\java_error_in_idea.hprof
16776 sun.tools.jps.Jps -mlv -Denv.class.path=.;D:\jdk\lib\dt.jar;D:\jdk\lib\tools.jar;  -Dapplication.home=D:\jdk -Xms8m

2. jstack    

    jstack主要用來查看某個Java進程內的線程堆棧信息。java

    jstack [option] pid  
    jstack [option] executable core  
    jstack [option] [server-id@]remote-hostname-or-ip

    -l long listings,會打印出額外的鎖信息,在發生死鎖時能夠用<strong>jstack -l pid</strong>來觀察鎖持有狀況  
    -m mixed mode,不只會輸出Java堆棧信息,還會輸出C/C++堆棧信息(好比Native方法)  

    jstack能夠定位到線程堆棧,根據堆棧信息咱們能夠定位到具體代碼,因此它在JVM性能調優中使用得很是多。下面咱們來一個實例找出某個Java進程中最耗費CPU的Java線程並定位堆棧信息,用到的命令有ps、top、printf、jstack、grep。

  第一步: 先找出Java進程ID,服務器上的Java應用名稱爲wordcount.jar:
root@ubuntu:/# ps -ef | grep mrf-center | grep -v grep
root     21711     1  1 14:47 pts/3    00:02:10 java -jar mrf-center.jar
 獲得進程ID爲21711,第二步找出該進程內最耗費CPU的線程,可使用ps -Lfp pid或者ps -mp pid -o THREAD, tid, time或者top -Hp pid,我這裏用第三個,輸出以下:


 TIME列就是各個Java線程耗費的CPU時間,CPU時間最長的是線程ID爲21742的線程,用
printf "%x\n" 21742
獲得21742的十六進制值爲54ee,下面會用到。    


    OK,下一步終於輪到jstack上場了,它用來輸出進程21711的堆棧信息,而後根據線程ID的十六進制值grep,以下:
root@ubuntu:/# jstack 21711 | grep 54ee
"PollIntervalRetrySchedulerThread" prio=10 tid=0x00007f950043e000 nid=0x54ee in Object.wait() [0x00007f94c6eda000]
  能夠看到CPU消耗在PollIntervalRetrySchedulerThread這個類的Object.wait(),我找了下個人代碼,定位到下面的代碼。
// Idle wait
getLog().info("Thread [" + getName() + "] is idle waiting...");
schedulerThreadState = PollTaskSchedulerThreadState.IdleWaiting;
long now = System.currentTimeMillis();
long waitTime = now + getIdleWaitTime();
long timeUntilContinue = waitTime - now;
synchronized(sigLock) {
  try {
    if(!halted.get()) {
      sigLock.wait(timeUntilContinue);
    }
  } 
  catch (InterruptedException ignore) {
  }
}
   它是輪詢任務的空閒等待代碼,上面的sigLock.wait(timeUntilContinue)就對應了前面的Object.wait()。


3. jmap(Memory Map)和jhat(Java Heap Analysis Tool)

  jmap用來查看堆內存使用情況,通常結合jhat使用。
 
  jmap語法格式以下:  
jmap [option] pid
jmap [option] executable core
jmap [option] [server-id@]remote-hostname-or-ip
 若是運行在64位JVM上,可能須要指定-J-d64命令選項參數。

(1) 打印進程的類加載器和類加載器加載的持久代對象信息,輸出:類加載器名稱、對象是否存活(不可靠)、對象地址、父類加載器、已加載的類大小等信息,以下圖:

     jmap -permstat pid


(2) 使用jmap -heap pid查看進程堆內存使用狀況,包括使用的GC算法、堆配置參數和各代中堆內存使用狀況。好比下面的例子:

    jmap -heap pid

[root@storm-master home]# jmap -heap 2860
Attaching to process ID 2860, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 20.45-b01

using thread-local object allocation.
Mark Sweep Compact GC

Heap Configuration:
   MinHeapFreeRatio = 40
   MaxHeapFreeRatio = 70
   MaxHeapSize      = 257949696 (246.0MB)
   NewSize          = 1310720 (1.25MB)
   MaxNewSize       = 17592186044415 MB
   OldSize          = 5439488 (5.1875MB)
   NewRatio         = 2
   SurvivorRatio    = 8
   PermSize         = 21757952 (20.75MB)
   MaxPermSize      = 85983232 (82.0MB)

Heap Usage:
New Generation (Eden + 1 Survivor Space):
   capacity = 12189696 (11.625MB)
   used     = 6769392 (6.4557952880859375MB)
   free     = 5420304 (5.1692047119140625MB)
   55.53372290826613% used
Eden Space:
   capacity = 10878976 (10.375MB)
   used     = 6585608 (6.280525207519531MB)
   free     = 4293368 (4.094474792480469MB)
   60.53518272307982% used
From Space:
   capacity = 1310720 (1.25MB)
   used     = 183784 (0.17527008056640625MB)
   free     = 1126936 (1.0747299194335938MB)
   14.0216064453125% used
To Space:
   capacity = 1310720 (1.25MB)
   used     = 0 (0.0MB)
   free     = 1310720 (1.25MB)
   0.0% used
tenured generation:
   capacity = 26619904 (25.38671875MB)
   used     = 15785896 (15.054603576660156MB)
   free     = 10834008 (10.332115173339844MB)
   59.30110040967841% used
Perm Generation:
   capacity = 33554432 (32.0MB)
   used     = 33323352 (31.779624938964844MB)
   free     = 231080 (0.22037506103515625MB)
   99.31132793426514% used
(3)查看堆內存中的對象數目、大小統計直方圖,若是帶上live則只統計活對象:
    
        jmap -histo[:live] pid

root@ubuntu:/# jmap -histo:live 21711 | more
 
 num     #instances         #bytes  class name
----------------------------------------------
   1:         38445        5597736  <constMethodKlass>
   2:         38445        5237288  <methodKlass>
   3:          3500        3749504  <constantPoolKlass>
   4:         60858        3242600  <symbolKlass>
   5:          3500        2715264  <instanceKlassKlass>
   6:          2796        2131424  <constantPoolCacheKlass>
   7:          5543        1317400  [I
   8:         13714        1010768  [C
   9:          4752        1003344  [B
  10:          1225         639656  <methodDataKlass>
  11:         14194         454208  java.lang.String
  12:          3809         396136  java.lang.Class
  13:          4979         311952  [S
  14:          5598         287064  [[I
  15:          3028         266464  java.lang.reflect.Method
  16:           280         163520  <objArrayKlassKlass>
  17:          4355         139360  java.util.HashMap$Entry
  18:          1869         138568  [Ljava.util.HashMap$Entry;
  19:          2443          97720  java.util.LinkedHashMap$Entry
  20:          2072          82880  java.lang.ref.SoftReference
  21:          1807          71528  [Ljava.lang.Object;
  22:          2206          70592  java.lang.ref.WeakReference
  23:           934          52304  java.util.LinkedHashMap
  24:           871          48776  java.beans.MethodDescriptor
  25:          1442          46144  java.util.concurrent.ConcurrentHashMap$HashEntry
  26:           804          38592  java.util.HashMap
  27:           948          37920  java.util.concurrent.ConcurrentHashMap$Segment
  28:          1621          35696  [Ljava.lang.Class;
  29:          1313          34880  [Ljava.lang.String;
  30:          1396          33504  java.util.LinkedList$Entry
  31:           462          33264  java.lang.reflect.Field
  32:          1024          32768  java.util.Hashtable$Entry
  33:           948          31440  [Ljava.util.concurrent.ConcurrentHashMap$HashEntry;

    class name是對象類型,說明以下:
算法

B  byte
C  char
D  double
F  float
I  int
J  long
Z  boolean
[  數組,如[I表示int[]
[L+類名 其餘對象
 還有一個很經常使用的狀況是:用jmap把進程內存使用狀況dump到文件中,再用jhat分析查看。jmap進行dump命令格式以下:

jmap -dump:format=b,file=dumpFileName
   同樣地對上面進程ID爲21711進行Dump:
root@ubuntu:/# jmap -dump:format=b,file=/tmp/dump.dat 21711     
Dumping heap to /tmp/dump.dat ...
Heap dump file created

   dump出來的文件能夠用MAT、VisualVM等工具查看,這裏用jhat查看:shell

root@ubuntu:/# jhat -port 9998 /tmp/dump.dat
Reading from /tmp/dump.dat...
Dump file created Tue Jan 28 17:46:14 CST 2014
Snapshot read, resolving...
Resolving 132207 objects...
Chasing references, expect 26 dots..........................
Eliminating duplicate references..........................
Snapshot resolved.
Started HTTP server on port 9998
Server is ready.
 而後就能夠在瀏覽器中輸入主機地址:9998查看了:


4.jstat(JVM統計監測工具)

    看看各個區內存和GC的狀況

    stat [ generalOption | outputOptions vmid [interval[s|ms] [count]] ]  
    vmid是Java虛擬機ID,在Linux/Unix系統上通常就是進程ID。interval是採樣時間間隔。count是採樣數目。好比下面輸出的是GC信息,採樣時間間隔爲250ms,採樣數爲6:
[root@storm-master Desktop]# jstat -gc 2860 250 6  

S0C、S1C、S0U、S1U:Survivor 0/1區容量(Capacity)和使用量(Used)  
EC、EU:Eden區容量和使用量  
OC、OU:年老代容量和使用量  
PC、PU:永久代容量和使用量  
YGC、YGT:年輕代GC次數和GC耗時  
FGC、FGCT:Full GC次數和Full GC耗時  
GCT:GC總耗時  

5.jinfo

    jinfo是jdk自帶的命令,用來查看jvm的配置參數。一般會先使用jps查看java進程的id,而後使用jinfo查看指定pid的jvm信息
    
    jinfo -flags process_id

jps
4704 Launcher
9680 RemoteMavenServer
4116
13052 Jps
jinfo -flags 9680
Debugger attached successfully.
Server compiler detected.
JVM version is 25.91-b15
Non-default VM flags: -XX:CICompilerCount=4 -XX:InitialHeapSize=268435456 -XX:MaxHeapSize=805306368 -XX:MaxNewSize=268435456 -XX:MinHeapDeltaBytes=524288 -XX:NewSize=89128960 -XX:OldSize=179306496 -XX:+UseCompressedClassPointers -XX:+UseCompressedOops -XX:+UseFastUnorderedTimeStamps -XX:-UseLargePagesIndividualAllocation -XX:+UseParallelGC
Command line:  -Djava.awt.headless=true -Didea.version==2017.1.1 -Xmx768m -Didea.maven.embedder.version=3.2.5 -Dfile.encoding=GBK

6.hprof(Heap/CPU Profiling Tool)

    hprof可以展示CPU使用率,統計堆內存使用狀況。
    2SE中提供了一個簡單的命令行工具來對java程序的cpu和heap進行 profiling,叫作HPROF。HPROF其實是JVM中的一個native的庫,它會在JVM啓動的時候經過命令行參數來動態加載,併成爲 JVM進程的一部分。若要在java進程啓動的時候使用HPROF,用戶能夠經過各類命令行參數類型來使用HPROF對java進程的heap或者 (和)cpu進行profiling的功能。HPROF產生的profiling數據能夠是二進制的,也能夠是文本格式的。這些日誌能夠用來跟蹤和分析 java進程的性能問題和瓶頸,解決內存使用上不優的地方或者程序實現上的不優之處。二進制格式的日誌還能夠被JVM中的HAT工具來進行瀏覽和分析,用 以觀察java進程的heap中各類類型和數據的狀況。在J2SE 5.0之後的版本中,HPROF已經被併入到一個叫作Java Virtual Machine Tool Interface(JVM TI)中。

java -agentlib:hprof[=options] ToBeProfiledClass  
java -Xrunprof[:options] ToBeProfiledClass  
javac -J-agentlib:hprof[=options] ToBeProfiledClass  
Option Name and Value  Description                    Default  
---------------------  -----------                    -------  
heap=dump|sites|all    heap profiling                 all  
cpu=samples|times|old  CPU usage                      off  
monitor=y|n            monitor contention             n  
format=a|b             text(txt) or binary output     a  
file=<file>            write data to file             java.hprof[.txt]  
net=<host>:<port>      send data over a socket        off  
depth=<size>           stack trace depth              4  
interval=<ms>          sample interval in ms          10  
cutoff=<value>         output cutoff point            0.0001  
lineno=y|n             line number in traces?         y  
thread=y|n             thread in traces?              n  
doe=y|n                dump on exit?                  y  
msa=y|n                Solaris micro state accounting n  
force=y|n              force output to <file>         y  
verbose=y|n            print messages about dumps     y  
- Get sample cpu information every 20 millisec, with a stack depth of 3:           java -agentlib:hprof=cpu=samples,interval=20,depth=3 classname       - Get heap usage information based on the allocation sites:           java -agentlib:hprof=heap=sites classname        上面每隔20毫秒採樣CPU消耗信息,堆棧深度爲3,生成的profile文件名稱是java.hprof.txt,在當前目錄。        默認狀況下,java進程profiling的信息(sites和dump)都會被 寫入到一個叫作java.hprof.txt的文件中。大多數狀況下,該文件中都會對每一個trace,threads,objects包含一個ID,每一 個ID表明一個不一樣的觀察對象。一般,traces會從300000開始。 默認,force=y,會將全部的信息所有輸出到output文件中,因此若是含有 多個JVMs都採用的HRPOF enable的方式運行,最好將force=n,這樣可以將單獨的JVM的profiling信息輸出到不一樣的指定文件。 interval選項只在 cpu=samples的狀況下生效,表示每隔多少毫秒對java進程的cpu使用狀況進行一次採集。 msa選項僅僅在Solaris系統下才有效, 表示會使用Solaris下的Micro State Accounting功能 .
相關文章
相關標籤/搜索