本文將介紹JDK自帶的JVM排查工具。其提供的排查工具備:
(1)jps:JVM Process Status Tool,顯示系統內全部的JVM進程;
(2)jstat:JVM Statistics Monitoring Tool,能夠收集JVM相關的運行數據;
(3)jinfo:Configuration Info for Java,顯示JVM配置信息;
(4)jmap:Memory Map for Java,用於生成JVM的內存快照;
(5)jhat:JVM Heap Dump Browser,用於分析heapdump文件,它能夠創建一個http/html服務,使用者能夠在瀏覽器上查看分析結果;
(6)jstack:Stack Trace for Java,顯示JVM的線程快照。
(7)jconsole:一個java GUI監視工具,能夠以圖表化的形式顯示各類數據。並可經過遠程鏈接監視遠程的服務器VM。
1、jps
列出正在運行的虛擬機進程,並顯示虛擬機執行主類名稱以及這些進程的本地虛擬機惟一id(Local Virtual Machine Identifier,簡稱LVMID)。相比其餘命令來講,它的功能其實比較單一,可是它的使用頻率確實很是高的,由於其餘的JDK命令大多都須要輸入虛擬機進程id。
注:看到這裏小夥伴們可能就會比較困惑了,由於在大多數使用JDK命令時,咱們都用的是pid(操做系統進程id)啊,那pid和LVMID到底有什麼區別呢?其實,很負責任的告訴你,對於本地虛擬機進程來講,它倆無差異,用ps命令也能夠查詢到,可是若是同時啓動多個虛擬機進程沒法根據進程名稱定位時,jps命令就派上用場了,能夠輸出主類名稱,經過主類名稱來區分。
jps命令格式:
jps命令格式
jps主要提供如下選項:
-q
只輸出LVMID,省略主類名稱;
-m
輸出虛擬機進程啓動時傳給主類函數的參數;
-l
輸出主類的完成package名稱或者jar包完整路徑名;
-v
輸出虛擬機啓動時的JVM參數
接下來咱們來看看它的實際使用:
測試代碼:
測試代碼
使用結果:
jps使用結果
2、jstat
用於監控虛擬機運行狀態信息。它能夠顯示本地或者遠程虛擬機進程的內存、垃圾收集、JIT編譯等運行數據。
jstat命令格式:
jstat命令格式
jstat命令稍許有些複雜,它主要有如下參數:
option:選項,jstat主要提供如下選項:
-class
監視類的裝載/卸載數量、總空間以及類裝載所耗時間;
-gc
監視java heap狀況,包括eden區和兩個survivor區、old區、永久區等的容量,已用空間和GC時間等信息;
-gccapacity
監視內容與-gc基本是一致的,-gccapacity的輸出包括heap各個區域使用到的最大最小空間;
gcutil
監視內容一樣與-gc基本一致,-gcutil的輸出主要是heap各個區域使用空間佔總空間百分比;
gccause
與-gcutil功能一致,可是會額外輸出致使上一次gc的緣由;
gcnew
監視young區gc狀況;
gcnewcapacity
監視內容與-gcnew基本相同,-gcnewcapacity的輸出包括使用到的最大最小空間;
-gcold
監視old區gc狀況;
-gcoldcapacity
監視內容與-gcold基本相同,-gcoldcapacity的輸出包括使用到的最大最小空間;
-gcpermcapacity
輸出永久代使用到的最大最小空間;
注:JDK 8廢除了永久代,引入了Metaspace,這個命令在JDK 8的環境下就不能使用了,那要看元數據空間相關狀況,使用-gcmetacapacity便可
-compiler
輸出JIT編譯器編譯過的方法以及耗時等信息;
-printcompilation
輸出以及被JIT編譯的方法
vmid:虛擬機進程id,這時候小夥伴們確定又要開始疑惑了,這個vmid與lvmid又有什麼區別?其實對於本地虛擬機進程,它倆沒任何區別,可是若是是遠程虛擬機進程,它倆就有區別了,遠程虛擬機進程vmid格式應該是這樣:
[protocol:][//] lvmid [@hostname[:port]/servername];
interval:查詢時間間隔;
count:查詢次數。
注:若是參數interval和count省略則表明只查詢一次;若是count省略的話,就會一直查詢。來個簡單的例子:jstat -gcnewcapacity 41503 1000,表示輸出進程41503的young區使用及gc狀況,每1000ms輸出一次。
接下來就部分option給出實例,同時分析下輸出。
jstat使用
jstat -class <vmid>
jstat -class輸出
Loaded:裝載的類的數量;
Bytes:裝載類所佔用的字節數;
Unloaded:卸載類數量;
Bytes:卸載類所佔用的字節數;
Time:裝載和卸載類所花時間。
jstat -compiler <vmid>
jstat -compiler輸出
Compiled:編譯任務執行數量;
Failed:編譯任務執行失敗數量;
Invalid:編譯任務執行失效數量;
Time:編譯任務消耗時間;
FailedType:最後一個編譯失敗任務的類型;
FailedMethod:最後一個編譯失敗任務所在的類及方法。
jstat -gc <vmid>
jstat -gc輸出
S0C:young區中的第一個survivor區的大小;
S1C:young區中的第二個survivor區的大小;
S0U:young區中的第一個survivor區目前已使用空間;
S1U:young區中的第二個survivor區目前已使用空間;
EC:young區中的eden區的大小;
EU:young區中的eden區目前已使用空間;
OC:old區的大小;
OU:old區目前已使用空間;
MC:元數據區大小;
MU:元數據區使用大小;
CCSC:壓縮類空間大小;
CCSU:壓縮類空間使用大小;
YGC:young gc次數;
YGCT:young gc消耗時間;
FGC:full gc次數;
FGCT:full gc消耗時間;
GCT:gc消耗時間。
jstat -gcutil <vmid>
jstat -gcutil輸出
S0:young區中的第一個survivor區的使用比例;
S1:young區中的第二個survivor區的使用比例;
E:young區中的eden區的使用比例;
O:old區使用比例;
M:元數據區使用比例;
CCS:壓縮類空間使用比例;
YGC:young gc次數;
YGCT:young gc消耗時間;
FGC:full gc次數;
FGCT:full gc消耗時間;
GCT:gc消耗時間。
jstat -gccapacity <vmid>
jstat -gccapacity輸出
NGCMN:young區最小容量;
NGCMX:young區最大容量;
NGC:當前young區容量;
S0C:young區中的第一個survivor區的大小;
S1C:young區中的第二個survivor區的大小;
EC:young區中的eden區的大小;
OGCMN:old區最小容量;
OGCMX:old區最大容量;
OGC:當前old區大小;
OC:當前old區的大小;
MCMN:元數據區最小容量;
MCMX:元數據區最大容量;
MC:當前元數據區大小;
CCSMN:壓縮類空間最小容量;
CCSMX:壓縮類空間最大容量;
CCSC:當前壓縮類空間大小;
YGC:young gc次數;
FGC:old gc次數。
jstat -gcnew <vmid>
jstat -gcnew輸出
S0C:young區中的第一個survivor區的大小;
S1C:young區中的第二個survivor區的大小;
S0U:young區中的第一個survivor區目前已使用空間;
S1U:young區中的第二個survivor區目前已使用空間;
TT:對象在young區存活的次數;
MTT:對象在young區存活的最大次數;
DSS:指望survivor區大小;
EC:young區中的eden區的大小;
EU:young區中的eden區目前已使用空間;
YGC:young gc次數;
YGCT:young gc消耗時間。
jstat -gcold <vmid>
jstat -gcold輸出
MC:元數據空間大小;
MU:元數據空間使用大小;
CCSC:壓縮類空間大小;
CCSU:壓縮類空間使用大小;
OC:old區大小;
OU:old區使用大小;
YGC:young gc次數;
FGC:full gc次數;
FGCT:full gc消耗時間;
GCT:gc消耗時間。
jstat -gcmetacapacity <vmid>
jstat -gcmetacapacity輸出
MCMN:元數據區最小容量;
MCMX:元數據區最大容量;
MC:元數據區大小;
CCSMN:壓縮類空間最小容量;
CCSMX:壓縮類空間最大容量;
CCSC:壓縮類空間大小;
YGC:young gc次數;
FGC:full gc次數;
FGCT:full gc消耗時間;
GCT:gc消耗時間。
jstat -printcompilation <vmid>
jstat -printcompilation輸出
Compiled:編譯方法數量;
Size:編譯方法的字節碼數量;
Type:編譯方法的編譯類型;
Method:方法名稱。
針對young區和old區相關capacity命令在這裏就不作詳細分析了,有興趣的小夥伴自行敲一敲命令運行下,至於輸出的表格列含義在前幾個命令詳細介紹中基本上都包括在內了。
注:在使用jstat命令輸出的容量的單位是字節。
3、jinfo
用於實時查看和調整虛擬機參數。
jinfo命令格式
jinfo命令格式
jinfo命令主要有如下參數:
option:選項,jinfo主要提供如下選項:
-flag <name>
輸出指定JVM參數值;
-flag [+|-]<name>
啓用或禁用指定JVM參數;
-flag <name>=<value>
設置指定JVM參數值;
-flags
輸出全部JVM參數
-sysprops
輸出Java系統屬性;
<no option>
不指定選項則輸出全部的虛擬機參數和Java系統屬性
pid:須要查看或者調整虛擬機參數的進程id
接下來咱們來看看它的實際使用:
jinfo使用結果
4、jmap
用於生成堆內存快照(heapdump或者dump文件)。固然,若是不想使用jmap命令,也可使用JVM參數來生成:
-XX:+HeapDumpOnOutOfMemoryError,若是虛擬機在出現OutOfMemory異常後生成dump文件;
-XX:+HeapDumpOnCtrlBreak,使用ctrl + break鍵讓虛擬機生成dump文件。
固然,還有一種更暴力的方式就是在linux系統下,kill -3也可讓虛擬機生成dump文件。
jmap命令格式
jmap命令格式
相比jstat命令,jmap命令明顯就簡單的多了,就兩個參數:
option:選項,jmap主要提供如下選項:
-dump
生成Java堆內存快照,使用格式爲:-dump:[live, ]format=b,file=<filename>,使用hprof二進制形式,輸出jvm的heap內容到文件<filename>,live子參數是可選的,若是指定live選項,就只dump出存活的對象;
finalizerinfo
顯示在F-Queue中等待Finalizer線程執行finalize方法的對象;
-heap
顯示heap詳細信息,好比使用哪一種回收器、參數配置、分代狀態等;
histo
顯示每一個class的實例數目,內存佔用,類全名信息。VM的內部類名字開頭會加上前綴「*」.,若是帶上live子參數,則只統計活的對象數量;
-permstat
以ClassLoader爲統計口徑顯示永久代內存狀態,須要注意的是,JDK 8將該option替換成了-clstats;
-F
強制生成dump文件,當虛擬機進程對-dump選項沒有響應時可使用。
pid:須要生成dump文件的進程id
dump文件在這裏我就不作演示了,給一個簡單的使用吧:
jmap -histo輸出
從輸出的結果能夠清晰的看出每個class的實例數目以及內存佔用狀況。
5、jstack
用戶生成虛擬機當前時刻的線程快照(threaddump/javacore文件)。線程快照就是當前虛擬機內每一條線程正在執行的方法堆棧集合,生成線程快照的目的也就是爲了定位線程出現長時間卡頓的緣由。
jstack命令格式
jstack命令格式
跟jmap命令同樣,jstack命令也只有兩個參數:
option:選項,jstack主要提供如下選項:
-F
當線程出現長時間卡頓的時候,強制輸出線程堆棧;
-l
除堆棧外,顯示關於鎖的附加信息;
-m
若是調用JNI方法,能夠顯示C/C++的堆棧。
pid:須要生成threaddump的進程id。
簡單給一個使用吧仍是:
jstack -l輸出
從輸出結果能夠清晰的看到線程堆棧以及鎖相關信息。具體的怎麼根據threaddump分析定位問題最近暫時沒有遇到,等遇到了再出文詳細介紹啦~
6、jhat
與jmap命令搭配使用,分析jmap生成的dump文件。jhat內置一個微型的HTTP/HTML服務器,生成dump文件的分析結果後,能夠在瀏覽器中進行查看。其實這個命令在實際生產中使用比較少,爲何不用的緣由我總結下來大概有兩點:第一呢,線上生產環境怎麼可能容許你在線上機器直接分析dump文件啊~~~第二就是jhat的分析功能相比其餘工具簡直是太簡陋了。
它的使用也很簡單啊,jhat <dump文件名稱>,等分析完就打開瀏覽器訪問相應的地址+端口就能夠愉快的開始分析dump文件了。
7、jconsole
jconsole是一個用java寫的GUI程序,用來監控VM,並可監控遠程的VM,很是易用,並且功能很是強。使用方法:命令行裏打 jconsole,選則進程就能夠了。
Console中關於內存分區的說明。
Eden Space (heap): 內存最初從這個線程池分配給大部分對象。
Survivor Space (heap):用於保存在eden space內存池中通過垃圾回收後沒有被回收的對象。
Tenured Generation (heap):用於保持已經在 survivor space內存池中存在了一段時間的對象。
Permanent Generation (non-heap): 保存虛擬機本身的靜態(refective)數據,例如類(class)和方法(method)對象。Java虛擬機共享這些類數據。這個區域被分割爲只讀的和只寫的,
Code Cache (non-heap):HotSpot Java虛擬機包括一個用於編譯和保存本地代碼(native code)的內存,叫作「代碼緩存區」(code cache)
---------------------
做者:samyang1
來源:CSDN
原文:https://blog.csdn.net/samyang1/article/details/80557619
版權聲明:本文爲博主原創文章,轉載請附上博文連接!html