天天看點

五、JDK指令行工具jps、jstat、jmap、jstack、jhat、jinfo

一、jps,檢視虛拟機程序的指令

五、JDK指令行工具jps、jstat、jmap、jstack、jhat、jinfo

參數說明

-q:隻輸出程序 ID

五、JDK指令行工具jps、jstat、jmap、jstack、jhat、jinfo

-m:輸出傳入 main 方法的參數

五、JDK指令行工具jps、jstat、jmap、jstack、jhat、jinfo

-l:輸出完全的包名,應用主類名,jar的完全路徑名

五、JDK指令行工具jps、jstat、jmap、jstack、jhat、jinfo

-v:輸出jvm參數

五、JDK指令行工具jps、jstat、jmap、jstack、jhat、jinfo

二、jstat,檢視虛拟機統計資訊監視指令

jstat -gcutil 程序id 多少毫秒查詢一次  共查詢多少次 ,檢視垃圾收集的狀況,例如下圖,程序号10066 ,1000毫秒查詢一次,總共查詢10次

五、JDK指令行工具jps、jstat、jmap、jstack、jhat、jinfo

這指令主要檢視堆記憶體gc情況,垃圾對象首先進入的是新生代Eden區,然後Eden沒有回收掉,進入S0,還沒有回收掉,進入S1區,當S1區使用滿了後,會發生一次YGC,但是不會是應用停止。這時垃圾對象還沒有被回收掉,就會進入到老年代Old區,當Old區使用滿了後,就會發生一次FGC,FGC會導緻應用停止,是以不能頻發的發生FGC,FGC代表發生FGC的次數,FGCT代表發生FGC的時間,如果FGC很大,就要定位是什麼原因導緻的頻繁發生FGC。這時可以使用jmap工具定位,或者Jvisualvm工具定位。

三、jinfo 檢視java配置資訊指令

1、jinfo process_id 輸出全部的參數和系統屬性

例如jinfo 10066

[[email protected] /]$ jinfo 10066
Attaching to process ID 10066, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 25.131-b11
Java System Properties:

java.runtime.name = Java(TM) SE Runtime Environment
java.vm.version = 25.131-b11
sun.boot.library.path = /home/njl/jdk1.8/jre/lib/amd64
java.protocol.handler.pkgs = org.apache.catalina.webresources
shared.loader = 
java.vendor.url = http://java.oracle.com/
java.vm.vendor = Oracle Corporation
path.separator = :
file.encoding.pkg = sun.io
java.vm.name = Java HotSpot(TM) 64-Bit Server VM
java.util.logging.config.file = /home/njl/apache-tomcat-8.5.15/conf/logging.properties
tomcat.util.buf.StringCache.byte.enabled = true
sun.os.patch.level = unknown
sun.java.launcher = SUN_STANDARD
user.country = US
tomcat.util.scan.StandardJarScanFilter.jarsToScan = log4j-web*.jar,log4j-taglib*.jar,log4javascript*.jar,slf4j-taglib*.jar
user.dir = /home/njl/apache-tomcat-8.5.15/bin
java.vm.specification.name = Java Virtual Machine Specification
java.runtime.version = 1.8.0_131-b11
java.awt.graphicsenv = sun.awt.X11GraphicsEnvironment
os.arch = amd64
java.endorsed.dirs = /home/njl/jdk1.8/jre/lib/endorsed
line.separator = 

java.io.tmpdir = /home/njl/apache-tomcat-8.5.15/temp
java.vm.specification.vendor = Oracle Corporation
java.util.logging.manager = org.apache.juli.ClassLoaderLogManager
java.naming.factory.url.pkgs = org.apache.naming
os.name = Linux
sun.jnu.encoding = UTF-8
java.library.path = /usr/java/packages/lib/amd64:/usr/lib64:/lib64:/lib:/usr/lib
java.class.version = 52.0
java.specification.name = Java Platform API Specification
sun.management.compiler = HotSpot 64-Bit Tiered Compilers
os.version = 3.10.0-693.2.2.el7.x86_64
java.util.concurrent.ForkJoinPool.common.threadFactory = org.apache.catalina.startup.SafeForkJoinWorkerThreadFactory
user.home = /home/njl
user.timezone = Asia/Shanghai
catalina.useNaming = true
java.awt.printerjob = sun.print.PSPrinterJob
file.encoding = UTF-8
java.specification.version = 1.8
tomcat.util.scan.StandardJarScanFilter.jarsToSkip = bootstrap.jar,commons-daemon.jar,tomcat-juli.jar,annotations-api.jar,el-api.jar,jsp-api.jar,servlet-api.jar,websocket-api.jar,jaspic-api.jar,catalina.jar,catalina-ant.jar,catalina-ha.jar,catalina-storeconfig.jar,catalina-tribes.jar,jasper.jar,jasper-el.jar,ecj-*.jar,tomcat-api.jar,tomcat-util.jar,tomcat-util-scan.jar,tomcat-coyote.jar,tomcat-dbcp.jar,tomcat-jni.jar,tomcat-websocket.jar,tomcat-i18n-en.jar,tomcat-i18n-es.jar,tomcat-i18n-fr.jar,tomcat-i18n-ja.jar,tomcat-juli-adapters.jar,catalina-jmx-remote.jar,catalina-ws.jar,tomcat-jdbc.jar,tools.jar,commons-beanutils*.jar,commons-codec*.jar,commons-collections*.jar,commons-dbcp*.jar,commons-digester*.jar,commons-fileupload*.jar,commons-httpclient*.jar,commons-io*.jar,commons-lang*.jar,commons-logging*.jar,commons-math*.jar,commons-pool*.jar,jstl.jar,taglibs-standard-spec-*.jar,geronimo-spec-jaxrpc*.jar,wsdl4j*.jar,ant.jar,ant-junit*.jar,aspectj*.jar,jmx.jar,h2*.jar,hibernate*.jar,httpclient*.jar,jmx-tools.jar,jta*.jar,log4j*.jar,mail*.jar,slf4j*.jar,xercesImpl.jar,xmlParserAPIs.jar,xml-apis.jar,junit.jar,junit-*.jar,hamcrest-*.jar,easymock-*.jar,cglib-*.jar,objenesis-*.jar,ant-launcher.jar,cobertura-*.jar,asm-*.jar,dom4j-*.jar,icu4j-*.jar,jaxen-*.jar,jdom-*.jar,jetty-*.jar,oro-*.jar,servlet-api-*.jar,tagsoup-*.jar,xmlParserAPIs-*.jar,xom-*.jar
catalina.home = /home/njl/apache-tomcat-8.5.15
user.name = njl
java.class.path = /home/njl/apache-tomcat-8.5.15/bin/bootstrap.jar:/home/njl/apache-tomcat-8.5.15/bin/tomcat-juli.jar
java.naming.factory.initial = org.apache.naming.java.javaURLContextFactory
package.definition = sun.,java.,org.apache.catalina.,org.apache.coyote.,org.apache.jasper.,org.apache.naming.,org.apache.tomcat.
java.vm.specification.version = 1.8
sun.arch.data.model = 64
sun.java.command = org.apache.catalina.startup.Bootstrap start
java.home = /home/njl/jdk1.8/jre
user.language = en
java.specification.vendor = Oracle Corporation
awt.toolkit = sun.awt.X11.XToolkit
java.vm.info = mixed mode
java.version = 1.8.0_131
java.ext.dirs = /home/njl/jdk1.8/jre/lib/ext:/usr/java/packages/lib/ext
sun.boot.class.path = /home/njl/jdk1.8/jre/lib/resources.jar:/home/njl/jdk1.8/jre/lib/rt.jar:/home/njl/jdk1.8/jre/lib/sunrsasign.jar:/home/njl/jdk1.8/jre/lib/jsse.jar:/home/njl/jdk1.8/jre/lib/jce.jar:/home/njl/jdk1.8/jre/lib/charsets.jar:/home/njl/jdk1.8/jre/lib/jfr.jar:/home/njl/jdk1.8/jre/classes
server.loader = 
java.vendor = Oracle Corporation
catalina.base = /home/njl/apache-tomcat-8.5.15
jdk.tls.ephemeralDHKeySize = 2048
file.separator = /
java.vendor.url.bug = http://bugreport.sun.com/bugreport/
common.loader = "${catalina.base}/lib","${catalina.base}/lib/*.jar","${catalina.home}/lib","${catalina.home}/lib/*.jar"
sun.io.unicode.encoding = UnicodeLittle
sun.cpu.endian = little
package.access = sun.,org.apache.catalina.,org.apache.coyote.,org.apache.jasper.,org.apache.tomcat.
sun.cpu.isalist = 

VM Flags:
Non-default VM flags: -XX:CICompilerCount=2 -XX:InitialHeapSize=31457280 -XX:MaxHeapSize=482344960 -XX:MaxNewSize=160759808 -XX:MinHeapDeltaBytes=196608 -XX:NewSize=10485760 -XX:OldSize=20971520 -XX:+UseCompressedClassPointers -XX:+UseCompressedOops 
Command line:  -Djava.util.logging.config.file=/home/njl/apache-tomcat-8.5.15/conf/logging.properties -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager -Djdk.tls.ephemeralDHKeySize=2048 -Djava.protocol.handler.pkgs=org.apache.catalina.webresources -Dcatalina.base=/home/njl/apache-tomcat-8.5.15 -Dcatalina.home=/home/njl/apache-tomcat-8.5.15 -Djava.io.tmpdir=/home/njl/apache-tomcat-8.5.15/temp
           

2、jinfo -flags process_id  檢視jvm的參數

[[email protected] /]$ jinfo -flags 10066
Attaching to process ID 10066, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 25.131-b11
Non-default VM flags: -XX:CICompilerCount=2 -XX:InitialHeapSize=31457280 -XX:MaxHeapSize=482344960 -XX:MaxNewSize=160759808 -XX:MinHeapDeltaBytes=196608 -XX:NewSize=10485760 -XX:OldSize=20971520 -XX:+UseCompressedClassPointers -XX:+UseCompressedOops 
Command line:  -Djava.util.logging.config.file=/home/njl/apache-tomcat-8.5.15/conf/logging.properties -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager -Djdk.tls.ephemeralDHKeySize=2048 -Djava.protocol.handler.pkgs=org.apache.catalina.webresources -Dcatalina.base=/home/njl/apache-tomcat-8.5.15 -Dcatalina.home=/home/njl/apache-tomcat-8.5.15 -Djava.io.tmpdir=/home/njl/apache-tomcat-8.5.15/temp
           

3、虛拟機的全部參數可以通過下面的指令檢視:

java -XX:+PrintFlagsFinal -version | grep manageable

[[email protected] /]$ java -XX:+PrintFlagsFinal -version | grep manageable
     intx CMSAbortablePrecleanWaitMillis            = 100                                 {manageable}
     intx CMSTriggerInterval                        = -1                                  {manageable}
     intx CMSWaitDuration                           = 2000                                {manageable}
     bool HeapDumpAfterFullGC                       = false                               {manageable}
     bool HeapDumpBeforeFullGC                      = false                               {manageable}
     bool HeapDumpOnOutOfMemoryError                = false                               {manageable}
    ccstr HeapDumpPath                              =                                     {manageable}
    uintx MaxHeapFreeRatio                          = 70                                  {manageable}
    uintx MinHeapFreeRatio                          = 40                                  {manageable}
     bool PrintClassHistogram                       = false                               {manageable}
     bool PrintClassHistogramAfterFullGC            = false                               {manageable}
     bool PrintClassHistogramBeforeFullGC           = false                               {manageable}
     bool PrintConcurrentLocks                      = false                               {manageable}
     bool PrintGC                                   = false                               {manageable}
     bool PrintGCDateStamps                         = false                               {manageable}
     bool PrintGCDetails                            = false                               {manageable}
     bool PrintGCID                                 = false                               {manageable}
     bool PrintGCTimeStamps                         = false                               {manageable}
java version "1.8.0_131"
Java(TM) SE Runtime Environment (build 1.8.0_131-b11)
Java HotSpot(TM) 64-Bit Server VM (build 25.131-b11, mixed mode)
           

四、jmap,用于生成堆轉儲快照,不用指令還可以用其他的方式,比如,-XX:+HeapDumpOnOutOfMemoryError參數,可以讓虛拟機在OOM異常出現之後自動生成dump檔案。jmap不僅擷取dump檔案,還可以查詢finalize執行隊列,java堆和永久代的詳細資訊。此指令主要是生成堆dump檔案使用的,定位堆記憶體溢出,代碼的位置,因為篇幅較長,就不在這細說了,如果大家感興趣可以看我的另外一篇部落格,https://blog.csdn.net/qq_30353203/article/details/68063733,如何使用jmap定位堆記憶體溢出穩定。

-dump

dump堆到檔案,format指定輸出格式,live指明是活着的對象,file指定檔案名

[[email protected] ~]$ jmap -dump:live,format=b,file=dump.hprof 10066
Dumping heap to /home/njl/dump.hprof ...
Heap dump file created
           

-heap

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

[[email protected] ~]$ jmap -heap 10066
Attaching to process ID 10066, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 25.131-b11

using thread-local object allocation.
Mark Sweep Compact GC

Heap Configuration:
   MinHeapFreeRatio         = 40
   MaxHeapFreeRatio         = 70
   MaxHeapSize              = 482344960 (460.0MB)
   NewSize                  = 10485760 (10.0MB)
   MaxNewSize               = 160759808 (153.3125MB)
   OldSize                  = 20971520 (20.0MB)
   NewRatio                 = 2
   SurvivorRatio            = 8
   MetaspaceSize            = 21807104 (20.796875MB)
   CompressedClassSpaceSize = 1073741824 (1024.0MB)
   MaxMetaspaceSize         = 17592186044415 MB
   G1HeapRegionSize         = 0 (0.0MB)

Heap Usage:
New Generation (Eden + 1 Survivor Space):
   capacity = 14745600 (14.0625MB)
   used     = 261600 (0.249481201171875MB)
   free     = 14484000 (13.813018798828125MB)
   1.7740885416666667% used
Eden Space:
   capacity = 13107200 (12.5MB)
   used     = 261600 (0.249481201171875MB)
   free     = 12845600 (12.250518798828125MB)
   1.995849609375% used
From Space:
   capacity = 1638400 (1.5625MB)
   used     = 0 (0.0MB)
   free     = 1638400 (1.5625MB)
   0.0% used
To Space:
   capacity = 1638400 (1.5625MB)
   used     = 0 (0.0MB)
   free     = 1638400 (1.5625MB)
   0.0% used
tenured generation:
   capacity = 32751616 (31.234375MB)
   used     = 17664680 (16.846351623535156MB)
   free     = 15086936 (14.388023376464844MB)
   53.935292841733364% used

16490 interned Strings occupying 2105240 bytes.
           

-finalizerinfo

列印等待回收的對象資訊

[[email protected] ~]$ jmap -finalizerinfo 10066
Attaching to process ID 10066, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 25.131-b11
Number of objects pending for finalization: 0
           

Number of objects pending 

for

finalization: 0 說明目前F-QUEUE隊列中并沒有等待Fializer線程執行finalizer方法的對象。

-histo

列印堆的對象統計,包括對象數、記憶體大小等等。jmap -histo:live 這個指令執行,JVM會先觸發gc,然後再統計資訊

[[email protected] ~]$ jmap -histo:live 10066 | more

 num     #instances         #bytes  class name
----------------------------------------------
   1:         53441        8252392  [C
   2:         52522        1260528  java.lang.String
   3:          5867         659824  java.lang.Class
   4:          7256         638528  java.lang.reflect.Method
   5:           977         628576  [B
   6:         17330         554560  java.util.HashMap$Node
   7:         11941         382112  java.util.concurrent.ConcurrentHashMap$Node
   8:          5846         341672  [Ljava.lang.Object;
   9:          1522         220056  [Ljava.util.HashMap$Node;
  10:          2912         157816  [I
  11:          4627         148064  java.lang.ref.WeakReference
  12:          6911         110576  java.lang.Object
  13:           113         109872  [Ljava.util.concurrent.ConcurrentHashMap$Node;
  14:          2527         101080  java.util.LinkedHashMap$Entry
           

五、jhat,檢視虛拟機堆記憶體指令

主要是用來分析java堆的指令,它與jmap搭配使用,來分析jmap生成的堆轉儲快照,jhat内置了一個微型的HTTP/HTML伺服器,生成的dump檔案的分析結果後,可以在浏覽器中檢視。但是一般不會直接用jhat這指令分析dump檔案,因為,一是一般不會在部署應用的伺服器上直接分析dump檔案,即使這樣做,也會盡量将dump檔案複制到其他機器上,因為分析工作是一個耗時而且消耗硬體資源的過程,既然要在其他機器上進行進行,就沒有必要使用指令行。二、是有個一可視化工具VisualVM和Ecplise裡的插件MAT,比jhat可以更好的分析堆轉儲快照。

使用指令jmap,打出的堆dump檔案,可以使用jhat這指令,分析堆檔案

[[email protected] ~]$ jhat dump.hprof 
Reading from dump.hprof...
Dump file created Mon Jan 21 20:19:06 CST 2019
Snapshot read, resolving...
Resolving 245665 objects...
Chasing references, expect 49 dots.................................................
Eliminating duplicate references.................................................
Snapshot resolved.
Started HTTP server on port 7000
Server is ready.
           

上圖中使用jhat指令打開了之前dump出來的堆快照檔案,可以看到,指令成功執行後會在指令執行的本機啟動一個http服務,可以在浏覽器上打開本機的7000端口檢視詳細的分析結果:

五、JDK指令行工具jps、jstat、jmap、jstack、jhat、jinfo

頁面中顯示了所有非平台類資訊,點選連結進入,可以檢視選中的類的超類,ClassLoader以及該類的執行個體等資訊。此外,在頁面的地步,jhat還可以提供了其他查詢方式。如圖所示:

五、JDK指令行工具jps、jstat、jmap、jstack、jhat、jinfo

分析結果是以包為機關進行分組顯示,分析記憶體漏洞主要使用其中的“Heap Histogram” 與OQL頁簽的功能,用Heap Histogram,找到記憶體中總容量最大的對象,OQL是标準的對象查詢語言,類似SQL的文法對記憶體中對象進行查詢統計,關于OQL大家感興趣可以自行檢視。

六、jstack,檢視虛拟機目前線程快照指令

這個指令也是比較常用的,一緻想要不要說怎麼使用,猶豫了一下,還是說一下怎麼使用,定位線程問題吧。

首先先寫一段代碼列印出目前線程名,注意行号顯示,後面會通過jstack定位到第幾行

五、JDK指令行工具jps、jstat、jmap、jstack、jhat、jinfo

把這段代碼打成jar包,上傳到伺服器中,然後運作指令,java -jar untitled.jar

這時使用top指令檢視使用cpu較高的程序

五、JDK指令行工具jps、jstat、jmap、jstack、jhat、jinfo

再使用top -Hp 28226 找到這個程序裡使用cpu最高的線程

五、JDK指令行工具jps、jstat、jmap、jstack、jhat、jinfo

然後把這個線程号轉換成為16進制,28236  轉成16進制為

五、JDK指令行工具jps、jstat、jmap、jstack、jhat、jinfo

這個時候我們可以使用jstack指令了,可以直接列印出線程dump,也可以把dump存到檔案,下載下傳到本地檢視,建議是下載下傳到本地。

五、JDK指令行工具jps、jstat、jmap、jstack、jhat、jinfo

然後,根據之前的線程id,是6e4c,在dump檔案中找到對應的線程,然後從下往上看,就可以發現我們剛才運作的方法,并且行号也顯示是15号,以此就是當cpu偏高的時候,怎麼使用jstack定位到哪行代碼的方法。

在以上指令中jps 、jstat、jmap、jstack,都是常用的定位性能瓶頸的指令工具,希望大家靈活運用。其實還有一些可是話工具,也是比較好用的比如,Jvisualvm,Jconsole,後面的有機會再給大家驗收如何使用