一、jps,檢視虛拟機程序的指令
參數說明
-q:隻輸出程序 ID
-m:輸出傳入 main 方法的參數
-l:輸出完全的包名,應用主類名,jar的完全路徑名
-v:輸出jvm參數
二、jstat,檢視虛拟機統計資訊監視指令
jstat -gcutil 程序id 多少毫秒查詢一次 共查詢多少次 ,檢視垃圾收集的狀況,例如下圖,程序号10066 ,1000毫秒查詢一次,總共查詢10次
這指令主要檢視堆記憶體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端口檢視詳細的分析結果:
頁面中顯示了所有非平台類資訊,點選連結進入,可以檢視選中的類的超類,ClassLoader以及該類的執行個體等資訊。此外,在頁面的地步,jhat還可以提供了其他查詢方式。如圖所示:
分析結果是以包為機關進行分組顯示,分析記憶體漏洞主要使用其中的“Heap Histogram” 與OQL頁簽的功能,用Heap Histogram,找到記憶體中總容量最大的對象,OQL是标準的對象查詢語言,類似SQL的文法對記憶體中對象進行查詢統計,關于OQL大家感興趣可以自行檢視。
六、jstack,檢視虛拟機目前線程快照指令
這個指令也是比較常用的,一緻想要不要說怎麼使用,猶豫了一下,還是說一下怎麼使用,定位線程問題吧。
首先先寫一段代碼列印出目前線程名,注意行号顯示,後面會通過jstack定位到第幾行
把這段代碼打成jar包,上傳到伺服器中,然後運作指令,java -jar untitled.jar
這時使用top指令檢視使用cpu較高的程序
再使用top -Hp 28226 找到這個程序裡使用cpu最高的線程
然後把這個線程号轉換成為16進制,28236 轉成16進制為
這個時候我們可以使用jstack指令了,可以直接列印出線程dump,也可以把dump存到檔案,下載下傳到本地檢視,建議是下載下傳到本地。
然後,根據之前的線程id,是6e4c,在dump檔案中找到對應的線程,然後從下往上看,就可以發現我們剛才運作的方法,并且行号也顯示是15号,以此就是當cpu偏高的時候,怎麼使用jstack定位到哪行代碼的方法。
在以上指令中jps 、jstat、jmap、jstack,都是常用的定位性能瓶頸的指令工具,希望大家靈活運用。其實還有一些可是話工具,也是比較好用的比如,Jvisualvm,Jconsole,後面的有機會再給大家驗收如何使用