原文:java
GitHub:github.com/wangzhiwubi…git
運用jvm自帶的命令能夠方便的在生產監控和打印堆棧的日誌信息幫忙咱們來定位問題!雖然jvm調優成熟的工具已經有不少:jconsole、大名鼎鼎的VisualVM,IBM的Memory Analyzer等等,可是在生產環境出現問題的時候,一方面工具的使用會有所限制,另外一方面喜歡裝X的咱們,總喜歡在出現問題的時候在終端輸入一些命令來解決。全部的工具幾乎都是依賴於jdk的接口和底層的這些命令,研究這些命令的使用也讓咱們更能瞭解jvm構成和特性。 Sun JDK監控和故障處理命令有jps jstat jmap jhat jstack jinfo下面作一一介紹github
全網惟一一個從0開始幫助Java開發者轉作大數據領域的公衆號~面試
公衆號大數據技術與架構或者搜索import_bigdata關注,大數據學習路線最新更新,已經有不少小夥伴加入了~算法
jps JVM Process Status Tool,顯示指定系統內全部的HotSpot虛擬機進程。apache
命令格式 jps [options] [hostid] option參數 -l : 輸出主類全名或jar路徑 -q : 只輸出LVMID -m : 輸出JVM啓動時傳遞給main()的參數 -v : 輸出JVM啓動時顯示指定的JVM參數 其中[option]、[hostid]參數也能夠不寫。bootstrap
示例數組
$ 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] : 連續輸出的次數tomcat
option 參數總覽 ![9ae139c199be662b76b7860da58f0f07](jvm系列(四)jvm調優-命令大全(jps jstat jmap jhat jstack jinfo).resources/3358A9D6-B4C7-4831-B26B-AD24973357EB.png)
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/DelegatingClassLoader@0x00000007800500a0
0x00000006008fcb48 1 1888 0x0000000600087f08 dead sun/reflect/DelegatingClassLoader@0x00000007800500a0
0x00000006016db798 0 0 0x00000006008d3fc0 dead java/util/ResourceBundle$RBClassLoader@0x0000000780626ec0
0x00000006008d6810 1 3056 null dead sun/reflect/DelegatingClassLoader@0x00000007800500a0
複製代碼
-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來進行分析,固然也看我的偏好。
分析 打開瀏覽器Http://localhost:7000,該頁面提供了幾個查詢功能可供使用:
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),平臺外的全部對象信息。以下圖: ![7f32f8469cc634a9c9a344ee905f9654](jvm系列(四)jvm調優-命令大全(jps jstat jmap jhat jstack jinfo).resources/E7DB83E0-2344-4149-8603-C606D78AB943.png) Show heap histogram 以樹狀圖形式展現堆狀況。以下圖:![80be25d2f1c6b019c28d96c42842fac6](jvm系列(四)jvm調優-命令大全(jps jstat jmap jhat jstack jinfo).resources/8DE752AB-6C96-4A58-8E01-8970BA3E2014.png) 具體排查時須要結合代碼,觀察是否大量應該被回收的對象在一直被引用或者是否有佔用內存特別大的對象沒法被回收。通常狀況,會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 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
複製代碼
關注公衆號,內推,面試,資源下載,關注更多大數據技術~
預計更新500+篇文章,已經更新50+篇~ 複製代碼