tags: java, troubleshooting, monitor,jvm
一句話概括:原來jdk自帶的命令行工具如此好用案糙,本文將詳細介紹时捌。
1 引言
監(jiān)測java應(yīng)用奢讨,最方便的就是直接使用jdk提供的現(xiàn)成工具禽笑,在jdk的安裝的bin目錄下佳镜,已經(jīng)提供了多種命令行監(jiān)測工具蟀伸,以便于開發(fā)人員和運維人員監(jiān)測java應(yīng)用和診斷問題啊掏,因此迟蜜,此類工具是java應(yīng)用監(jiān)測的重要手段娜睛。也是作為java開發(fā)人員需要掌握的基本技能畦戒。
2 常用監(jiān)測命令行工具
一般來說障斋,常用的命令行工具包括jps
,jinfo
,jmap
,jstack
,jstat
垃环,這些工具都在JAVA_HOME/bin/
目錄下遂庄,概要說明如下:
-
jps
查看java進程ID -
jinfo
查看及調(diào)整虛擬機參數(shù) -
jmap
查看堆(heap)使用情況及生成堆快照 -
jstack
查看線程運行狀態(tài)及生成線程快照 -
jstat
顯示進程中的類裝載涧团、內(nèi)存泌绣、垃圾收集等運行數(shù)據(jù)阿迈。
通過這些工具苗沧,基本上可以了解java應(yīng)用的內(nèi)存變化狀態(tài)待逞,線程運行狀態(tài)等信息识樱,進而為應(yīng)用監(jiān)測及問題診斷提供依據(jù)。下面將結(jié)合實例對這些工具的使用進行詳細講解当犯,文中所使用的示例代碼java-monitor-example
已上傳到我的github嚎卫,地址:https://github.com/mianshenglee
拓诸。
3 進程查詢工具jps
3.1 jps
說明
要監(jiān)測java應(yīng)用恰响,第一步就是先知道這個應(yīng)用是哪個進程胚宦,它的運行參數(shù)是什么井联。jps
就是可以查詢進程的工具您旁。熟悉linux的同學(xué)鹤盒,大概都知道查詢進程使用ps -ef|grep java
這樣的命令驼鞭,jps也類似挣棕,但它不使用名稱查找洛心,而是查找全部當(dāng)前jdk運行的java進程词身,而且只查找當(dāng)前用戶的Java進程偿枕,而不是當(dāng)前系統(tǒng)中的所有進程。
3.2 jps
使用
作為命令行工具渔欢,可以通過-help
參數(shù)查看幫助奥额,也可查閱官方文檔:https://docs.oracle.com/javase/8/docs/technotes/tools/unix/jps.html
垫挨,如下:
[root@test bin]# jps -help
usage: jps [-help]
jps [-q] [-mlvV] [<hostid>]
Definitions:
<hostid>: <hostname>[:<port>]
參數(shù)解釋:
-q:只顯示java進程的pid
-m:輸出傳遞給main方法的參數(shù)九榔,在嵌入式j(luò)vm上可能是null
-l:輸出應(yīng)用程序main class的完整package名 或者 應(yīng)用程序的jar文件完整路徑名
-v:輸出傳遞給JVM的參數(shù)
示例工程java-monitor-example
在linux機器中運行起來剩蟀,使用jps
可輸出以下信息:
- 只輸出進程ID
[root@test bin]# jps -q
13680
14214
- 輸出程序完整名稱及JVM參數(shù)
[root@test bin]# jps -lv
13680 java-monitor-example-0.0.1-SNAPSHOT.jar -Xms128m -Xmx128m -Dserver.port=8083
14289 sun.tools.jps.Jps -Denv.class.path=.:/opt/jdk8/lib:/opt/jdk8/jre/lib -Dapplication.home=/opt/jdk8
輸出的內(nèi)容中育特,java-monitor-example-0.0.1-SNAPSHOT.jar
是-l
輸出的完整名稱缰冤,-Xms128m -Xmx128m -Dserver.port=8083
是傳給JVM的參數(shù)锋谐。
- 在shell腳本中使用命令獲取java進程ID并作為變量使用
JAVA_HOME="/opt/jdk8"
APP_MAINCLASS=java-monitor-example
#初始化psid變量(全局)
psid=0
#查看進程ID函數(shù)
checkpid() {
javaps=`$JAVA_HOME/bin/jps -l | grep $APP_MAINCLASS`
if [ -n "$javaps" ]; then
psid=`echo $javaps | awk '{print $1}'`
else
psid=0
fi
}
#調(diào)用函數(shù)后通過psid進行業(yè)務(wù)邏輯操作,如根據(jù)進程id殺進程
checkpid
echo "(pid=$psid)"
上述腳本三热,比較適合運維人員對應(yīng)用的開啟和關(guān)閉就漾,自動獲取java進程ID抑堡,然后根據(jù)ID判斷程序是否運行(start)首妖,或者關(guān)閉應(yīng)用(kill -9
)有缆。
4 配置信息工具jinfo
4.1 jinfo
說明
知道java應(yīng)用所屬的進程號是第一步棚壁,在上一篇文章《java應(yīng)用監(jiān)測(2)-java命令的秘密》中袖外,已經(jīng)知道java的啟動參數(shù)有很多曼验,監(jiān)測java應(yīng)用前需要了解清楚它的啟動參數(shù)是什么魄幕。這時就需要用到jinfo
工具。jinfo
可以輸出JAVA應(yīng)用的系統(tǒng)參數(shù)和JVM參數(shù)颖杏。jinfo還能夠修改一部分運行期間能夠調(diào)整的虛擬機參數(shù)纯陨,很多運行參數(shù)是不能調(diào)整的,如果出現(xiàn)"cannot be changed"異常留储,說明不能調(diào)整翼抠。不過官方文檔指出,這個命令在后續(xù)的版本中可能不再使用获讳,當(dāng)前JDK8還是可以用的。
4.2 jinfo
使用
通過-help
參數(shù)查看幫助丐膝,也可查閱jinfo
官方文檔說明:https://docs.oracle.com/javase/8/docs/technotes/tools/unix/jinfo.html
量愧,如下:
[root@test bin]# jinfo -help
Usage:
jinfo [option] <pid>
(to connect to running process)
where <option> is one of:
-flag <name> to print the value of the named VM flag
-flag [+|-]<name> to enable or disable the named VM flag
-flag <name>=<value> to set the named VM flag to the given value
-flags to print VM flags
-sysprops to print Java system properties
<no option> to print both of the above
-h | -help to print this help message
使用jps
獲取到應(yīng)用的進程ID后(示例的PID為13680),如果直接jps <pid>
則會輸出全部的系統(tǒng)參數(shù)和JVM參數(shù)帅矗,其它參數(shù)說明在help
中也說得很清楚了偎肃。下面還是結(jié)合示例代碼java-monitor-example
來實踐一下:
- 獲取java應(yīng)用的堆初始值
[root@test bin]# jinfo -flag InitialHeapSize 13680
-XX:InitialHeapSize=134217728
- 查看全部的JVM參數(shù)
[root@test bin]# jinfo -flags 13680
Attaching to process ID 13680, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 25.51-b03
Non-default VM flags: -XX:CICompilerCount=2 -XX:InitialHeapSize=134217728 -XX:MaxHeapSize=134217728 -XX:MaxNewSize=44564480 -XX:MinHeapDeltaBytes=524288 -XX:NewSize=44564480 -XX:OldSize=89653248 -XX:+UseCompressedClassPointers -XX:+UseCompressedOops -XX:+UseFastUnorderedTimeStamps -XX:+UseParallelGC
Command line: -Xms128m -Xmx128m -Dserver.port=8083
可見,由于我們啟動時設(shè)置了-Xms
和-Xmx
浑此,它們對應(yīng)的就是-XX:InitialHeapSize
及-XX:MaxHeapSize
值累颂。另外,參數(shù)-Dserver.port
屬于系統(tǒng)參數(shù)凛俱,使用jinfo -sysprops 13680
就可以查看系統(tǒng)參數(shù)了紊馏。
5 堆內(nèi)存查看工具jmap
5.1 jmap
說明
java應(yīng)用啟動后,它在JVM中運行蒲犬,內(nèi)存是需要重點監(jiān)測的地方朱监,jmap
就是這樣的一個工具,它可以獲取運行中的jvm的堆的快照暖哨,包括整體情況赌朋,堆占用情況的直方圖凰狞,dump出快照文件以便于離線分析等篇裁。官方文檔指出沛慢,這個命令在后續(xù)的版本中可能不再使用,當(dāng)前JDK8還是可以用的达布。
5.2 jmap
使用
通過-help
參數(shù)查看幫助团甲,也可查閱jmap
官方文檔說明:https://docs.oracle.com/javase/8/docs/technotes/tools/unix/jmap.html
,幫助說明如下:
[root@test bin]# jmap -help
Usage:
jmap [option] <pid>
(to connect to running process)
where <option> is one of:
<none> to print same info as Solaris pmap
-heap to print java heap summary
-histo[:live] to print histogram of java object heap; if the "live"
suboption is specified, only count live objects
-clstats to print class loader statistics
-finalizerinfo to print information on objects awaiting finalization
-dump:<dump-options> to dump java heap in hprof binary format
dump-options:
live dump only live objects; if not specified,
all objects in the heap are dumped.
format=b binary format
file=<file> dump heap to <file>
Example: jmap -dump:live,format=b,file=heap.bin <pid>
-F force. Use with -dump:<dump-options> <pid> or -histo
to force a heap dump or histogram when <pid> does not
respond. The "live" suboption is not supported
in this mode.
-h | -help to print this help message
-J<flag> to pass <flag> directly to the runtime system
如上所示黍聂,jmap
參數(shù)常用的是-heap
,-histo
和-dump
躺苦,結(jié)合示例java-monitor-example
,說明如下:
- 打印jvm內(nèi)存整體使用情況
[root@test bin]# jmap -heap 13680
Attaching to process ID 13680, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 25.51-b03
using thread-local object allocation.
Parallel GC with 2 thread(s)
Heap Configuration:
MinHeapFreeRatio = 0
MaxHeapFreeRatio = 100
MaxHeapSize = 134217728 (128.0MB)
NewSize = 44564480 (42.5MB)
MaxNewSize = 44564480 (42.5MB)
OldSize = 89653248 (85.5MB)
NewRatio = 2
SurvivorRatio = 8
MetaspaceSize = 21807104 (20.796875MB)
CompressedClassSpaceSize = 1073741824 (1024.0MB)
MaxMetaspaceSize = 17592186044415 MB
G1HeapRegionSize = 0 (0.0MB)
Heap Usage:
PS Young Generation
Eden Space:
capacity = 31981568 (30.5MB)
used = 5306632 (5.060798645019531MB)
free = 26674936 (25.43920135498047MB)
16.59278244268699% used
From Space:
capacity = 6291456 (6.0MB)
used = 1081440 (1.031341552734375MB)
free = 5210016 (4.968658447265625MB)
17.18902587890625% used
To Space:
capacity = 6291456 (6.0MB)
used = 0 (0.0MB)
free = 6291456 (6.0MB)
0.0% used
PS Old Generation
capacity = 89653248 (85.5MB)
used = 16615680 (15.845947265625MB)
free = 73037568 (69.654052734375MB)
18.533271655701753% used
18006 interned Strings occupying 2328928 bytes.
從以上信息产还,可以看出JVM中堆內(nèi)存當(dāng)前的使用情況匹厘,包括年輕代(Eden
區(qū),From
區(qū)脐区,To
區(qū))和年老代愈诚。
- 查看類名,對象數(shù)量牛隅,對象占用大小直方圖
[root@test bin]# jmap -histo:live 13680|more
num #instances #bytes class name
----------------------------------------------
1: 36536 6462912 [C
2: 35557 853368 java.lang.String
3: 7456 826968 java.lang.Class
4: 20105 643360 java.util.concurrent.ConcurrentHashMap$Node
5: 1449 469024 [B
6: 6951 399280 [Ljava.lang.Object;
7: 9311 297952 java.util.HashMap$Node
8: 3122 274736 java.lang.reflect.Method
9: 2884 269112 [I
10: 6448 257920 java.util.LinkedHashMap$Entry
11: 2994 255160 [Ljava.util.HashMap$Node;
12: 15249 243984 java.lang.Object
.....
.....
如上所示炕柔,使用-histo
輸出包括序號,實例數(shù)媒佣,占用字節(jié)數(shù)和類名稱匕累。具體說明如下:
- instances列:表示當(dāng)前類有多少個實例。
- bytes列:說明當(dāng)前類的實例總共占用了多少個字節(jié)
- class name列:表示的就是當(dāng)前類的名稱默伍,class name 解讀:
- B代表byte
- C代表char
- D代表double
- F代表float
- I代表int
- J代表long
- Z代表boolean
- [代表數(shù)組欢嘿,如[I相當(dāng)于int[]
- 對象用[L+類名表示
- 把內(nèi)存情況dump內(nèi)存到本地文件
[root@test bin]# jmap -dump:file=./heap.hprof 13680
如上所示,會把堆情況寫入到當(dāng)前目錄的heap.hprof
文件中也糊,至于如何分析此文件炼蹦,可以使用jhat
,但一般實際開發(fā)中显设,很少使用jhat來直接對內(nèi)存dump文件進行分析框弛,因此不再對它進行講述。更多的是使用工具MAT
捕捂,以可視化的方式來查看瑟枫,后續(xù)文章將會對MAT
工具的使用進行詳細講解。
6 線程棧查詢工具jstack
6.1 jstack
說明
此命令打印指定Java應(yīng)用的線程堆棧指攒,對于每個Java幀慷妙,將打印完整的類名,方法名允悦,字節(jié)代碼索引(BCI)和行號膝擂,可以用于檢測死鎖,線程停頓,進程耗用cpu過高報警問題等排查架馋。
6.2 jstack
使用
使用-help
參數(shù)查看幫助狞山,也可查閱jstack
官方文檔說明:https://docs.oracle.com/javase/8/docs/technotes/tools/unix/jstack.html
,幫助說明如下:
[root@test bin]# jstack -help
Usage:
jstack [-l] <pid>
(to connect to running process)
jstack -F [-m] [-l] <pid>
Options:
-F 強制dump線程堆棧信息. 用于進程hung住叉寂, jstack <pid>命令沒有響應(yīng)的情況
-m 同時打印java和本地(native)線程棧信息萍启,m是mixed mode的簡寫
-l 打印鎖的額外信息
結(jié)合示例java-monitor-example
,可以打印線程信息(一般都會把打印的內(nèi)容寫入到文件然后再分析)屏鳍,如下:
- 打印當(dāng)前線程堆棧信息
[root@test bin]# jstack 13680
2019-08-16 23:18:18
Full thread dump Java HotSpot(TM) 64-Bit Server VM (25.51-b03 mixed mode):
"http-nio-8083-Acceptor-0" #39 daemon prio=5 os_prio=0 tid=0x00007f7520698800 nid=0x359a runnable [0x00007f7508bb7000]
java.lang.Thread.State: RUNNABLE
at sun.nio.ch.ServerSocketChannelImpl.accept0(Native Method)
at sun.nio.ch.ServerSocketChannelImpl.accept(ServerSocketChannelImpl.java:422)
at sun.nio.ch.ServerSocketChannelImpl.accept(ServerSocketChannelImpl.java:250)
- locked <0x00000000f8c85380> (a java.lang.Object)
at org.apache.tomcat.util.net.NioEndpoint.serverSocketAccept(NioEndpoint.java:448)
at org.apache.tomcat.util.net.NioEndpoint.serverSocketAccept(NioEndpoint.java:70)
at org.apache.tomcat.util.net.Acceptor.run(Acceptor.java:95)
at java.lang.Thread.run(Thread.java:745)
6.3 線程dump分析
6.3.1 線程狀態(tài)
java線程棧使用jstack
dump出來后勘纯,可以看到線程的狀態(tài),線程狀態(tài)一共分6種钓瞭,可以參考官方文檔:https://docs.oracle.com/javase/8/docs/technotes/guides/troubleshoot/tooldescr034.html
驳遵,下面是它的狀態(tài)說明:
- NEW
線程已經(jīng)new出來創(chuàng)建了,但是還沒有啟動(not yet started),jstack
不會打印這個狀態(tài)的線程信息山涡。
- RUNNABLE
正在Java虛擬機下跑任務(wù)的線程的狀態(tài)堤结,但其實它是只是表示線程是可運行的(ready)。對于單核的CPU佳鳖,多個線程在同一時刻霍殴,只能運行一個線程,其它的則需要等CPU的調(diào)度系吩。
- BLOCKED
線程處于阻塞狀態(tài)来庭,正在等待一個鎖,多個線程共用一個鎖穿挨,當(dāng)某線程正在使用這個鎖進入某個synchronized同步方法塊或者方法月弛,而此線程需要進入這個同步代碼塊,也需要這個鎖科盛,則導(dǎo)致本線程處于阻塞狀態(tài)帽衙。
- WAITING
等待狀態(tài),處于等待狀態(tài)的線程是由于執(zhí)行了3個方法中的任意方法贞绵。 1. Object.wait
方法厉萝,并且沒有使用timeout參數(shù); 2. Thread.join
方法,沒有使用timeout參數(shù) 3. LockSupport.park
方法榨崩。 處于waiting狀態(tài)的線程會等待另外一個線程處理特殊的行為谴垫。一個線程處于等待狀態(tài)(wait,通常是在等待其他線程完成某個操作(notify或者notifyAll)母蛛。注意翩剪,Object.wait()
方法只能夠在同步代碼塊中調(diào)用。調(diào)用了wait()
方法后彩郊,會釋放鎖前弯。
- TIMED_WAITING
線程等待指定的時間蚪缀,對于以下方法的調(diào)用,可能會導(dǎo)致線程處于這個狀態(tài):1. Thread.sleep方法 2. Object.wait
方法恕出,帶有時間 3. Thread.join
方法询枚,帶有時間 4. LockSupport.parkNanos
方法,帶有時間 5. LockSupport.parkUntil
方法剃根,帶有時間哩盲。注意前方,Thread.sleep
方法調(diào)用后狈醉,它不會釋放鎖,仍然占用系統(tǒng)資源惠险。
- TERMINATED
線程中止的狀態(tài)苗傅,這個線程已經(jīng)完整地執(zhí)行了它的任務(wù)。
從下面這張圖可以看出線程狀態(tài)的變化情況:
6.3.2 分析jstack
后線程棧內(nèi)容
從前面使用jstack
dump出來信息班巩,我們需要知道以下幾個信息:
-
"http-nio-8083-Acceptor-0" #39
:是線程的名字渣慕,因此,一般我們創(chuàng)建線程時需要設(shè)置自己可以辯識的名字抱慌。 -
daemon
表示線程是否是守護線程 -
prio
表示我們?yōu)榫€程設(shè)置的優(yōu)先級 -
os_prio
表示的對應(yīng)的操作系統(tǒng)線程的優(yōu)先級逊桦,由于并不是所有的操作系統(tǒng)都支持線程優(yōu)先級,所以可能會出現(xiàn)都置為0的情況 -
tid
線程的id -
nid
線程對應(yīng)的操作系統(tǒng)本地線程id抑进,每一個java線程都有一個對應(yīng)的操作系統(tǒng)線程强经,它是16進制的,因此一般在操作系統(tǒng)中獲取到線程ID后寺渗,需要轉(zhuǎn)為16進制匿情,來對應(yīng)上。 -
java.lang.Thread.State: RUNNABLE
運行狀態(tài)信殊,上面已經(jīng)介紹了線程的狀態(tài)炬称,若是WAITING狀態(tài),則括號中的內(nèi)容說明了導(dǎo)致等待的原因涡拘,如parking說明是因為調(diào)用了LockSupport.park方法導(dǎo)致等待玲躯。通常的堆棧信息中,都會有l(wèi)ock標記鳄乏,如- locked <0x00000000f8c85380> (a java.lang.Object)
表示正在占用這個鎖跷车。 - 對于線程停頓,CPU占用等問題汞窗,可以重點看一下
wait
狀態(tài)的線程 - 對于死鎖姓赤,在Dump出來的線程棧快照可以直接報告出Java級別的死鎖仲吏。
7 JVM統(tǒng)計數(shù)據(jù)工具jstat
7.1 jstat
說明
jstat
即JVM Statistics Monitoring Tool
不铆,即JVM統(tǒng)計監(jiān)測工具蝌焚,包括監(jiān)測類裝載、內(nèi)存誓斥、垃圾收集只洒、JIT編譯等運行數(shù)據(jù),在沒有圖形的服務(wù)器上劳坑,它是運行期定位虛擬機性能問題的首選工具毕谴。
7.2 jstat
使用
使用-help
參數(shù)查看幫助,也可查閱jstat
官方文檔說明:https://docs.oracle.com/javase/8/docs/technotes/tools/unix/jstat.html
距芬,幫助說明如下:
[root@test bin]# jstat -help
jstat -<option> [-t] [-h<lines>] <vmid> [<interval> [<count>]]
Usage: jstat -help|-options
jstat -<option> [-t] [-h<lines>] <vmid> [<interval> [<count>]]
Definitions:
<option> An option reported by the -options option
<vmid> Virtual Machine Identifier. A vmid takes the following form:
<lvmid>[@<hostname>[:<port>]]
Where <lvmid> is the local vm identifier for the target
Java virtual machine, typically a process id; <hostname> is
the name of the host running the target Java virtual machine;
and <port> is the port number for the rmiregistry on the
target host. See the jvmstat documentation for a more complete
description of the Virtual Machine Identifier.
<lines> Number of samples between header lines.
<interval> Sampling interval. The following forms are allowed:
<n>["ms"|"s"]
Where <n> is an integer and the suffix specifies the units as
milliseconds("ms") or seconds("s"). The default units are "ms".
<count> Number of samples to take before terminating.
-J<flag> Pass <flag> directly to the runtime system.
以上所示涝开,vmid
、interval
框仔、count
分別是進程號舀武,打印間隔時間(s或ms),打印次數(shù)离斩,其中option
參數(shù)主要是以下(也可以使用命令jstat -option
查看):
-
-class
統(tǒng)計class loader行為信息 银舱,如總共加載了多少個類 -
-compile
統(tǒng)計HotSpot Just-in-Time編譯器的行為 -
-gc
統(tǒng)計jdk gc時heap信息 -
-gccapacity
統(tǒng)計不同的generations相應(yīng)的heap容量情況 -
-gccause
統(tǒng)計gc的情況,(同-gcutil)和引起gc的事件 -
-gcnew
統(tǒng)計gc時跛梗,新生代的情況 -
-gcnewcapacity
統(tǒng)計gc時寻馏,新生代heap容量 -
-gcold
統(tǒng)計gc時,老年區(qū)的情況 -
-gcoldcapacity
統(tǒng)計gc時核偿,老年區(qū)heap容量 -
-gcpermcapacity
統(tǒng)計gc時诚欠,permanent區(qū)heap容量 -
-gcutil
統(tǒng)計gc時,heap情況 -
-printcompilation
hotspot編譯方法統(tǒng)計
一般我們使用-class
宪祥,-gc
聂薪,-gccause
和-gcutil
比較多,主要用于來分析類和堆使用情況及gc情況蝗羊。
7.3 監(jiān)測JVM的GC情況
以上述的示例工程java-monitor-example
為例藏澳,里面包含了一個函數(shù)來測試內(nèi)存溢出(使用一個數(shù)組,循環(huán)創(chuàng)建對象耀找,直到內(nèi)存溢出)翔悠。使用jstat -gc 13680 1000
即每秒監(jiān)測一次,調(diào)用/monitor/user/oom
接口后野芒,即看到堆和GC變化情況蓄愁。為方便查看,我把輸出放到sublime中顯示狞悲,如下所示:
日志輸出OOM報錯:
以上輸出的內(nèi)容撮抓,每列的說明如下:
-
S0C
當(dāng)前年輕代中第一個survivor(s0)的總?cè)萘?(KB). -
S1C
當(dāng)前年輕代中第一個survivor(s1)的總?cè)萘?(KB). -
S0U
s0已使用的容量 (KB). -
S1U
s1已使用的容量 (KB). -
EC
當(dāng)前年輕代中eden區(qū)總?cè)萘?(KB). -
EU
eden區(qū)已經(jīng)使用的容量 (KB). -
OC
年老代的容量總?cè)萘?(KB). -
OU
年老代已使用容量(KB). -
MC
當(dāng)前 Metaspace總?cè)萘?KB). -
MU
當(dāng)前 Metaspace已使用容量 (KB). -
CCSC
Compressed class容量大小 -
CCSU
Compressed class已使用容量 -
YGC
從應(yīng)用啟動時到現(xiàn)在,年輕代young generation 發(fā)生GC Events的總次數(shù). -
YGCT
從應(yīng)用啟動時到現(xiàn)在摇锋, 年輕代Young generation 垃圾回收的總耗時. -
FGC
從應(yīng)用啟動時到現(xiàn)在丹拯, full GC事件總次數(shù). -
FGCT
從應(yīng)用啟動時到現(xiàn)在站超, Full sc總耗時.GCT 從應(yīng)用啟動時到現(xiàn)在, 垃圾回收總時間. -GCT
GCT=YGCT+FGCT
從以上輸出第6行可以看出乖酬,EC
和EU
死相,OC
和OU
表示年輕代、年老代的內(nèi)存都已經(jīng)用完(與容量數(shù)值相等)咬像,發(fā)生OOM算撮。這時,則需要采取措施县昂,增大內(nèi)存(-Xmx參數(shù))或者找到導(dǎo)致OOM的代碼進行修改肮柜。
8 總結(jié)
針對java應(yīng)用的監(jiān)測,本文對jdk提供自身提供的命令行工具進行了說明和使用的介紹七芭,完整的描述了查看java應(yīng)用進程素挽,查看啟動參數(shù),查看內(nèi)存情況狸驳,查看線程情況,查看內(nèi)存統(tǒng)計情況等缩赛,主要是jps
耙箍,jinfo
,jmap
酥馍,jstack
辩昆,jstat
5個工具,并結(jié)合實例旨袒,希望學(xué)習(xí)java開發(fā)人員都能掌握這些技術(shù)汁针,在監(jiān)測java應(yīng)用時,可以從容面對如OOM砚尽,CPU高施无,線程停頓等問題。
參考資料
-
JDK工具參考文檔:
https://docs.oracle.com/javase/8/docs/technotes/tools/unix/
-
示例代碼
java-monitor-example
:https://github.com/mianshenglee/my-example/tree/master/java-monitor-example
-
Java開發(fā)必須掌握的線上問題排查命令:
https://www.hollischuang.com/archives/1561
-
Java自帶的性能監(jiān)測工具:
http://www.tianshouzhi.com/api/tutorials/jvm/346