性能監(jiān)控與故障處理工具
命令行工具:jps、jinfo、jstack、jmap、jstat、jstatd、jcmd。
圖形化工具:JConsole、jmc、VisualVM。
兩種連接方式:JMX、jstatd。
JVM監(jiān)控工具的作用
1、對(duì)JVM運(yùn)行期間的內(nèi)部情況進(jìn)行監(jiān)控,比如:對(duì)JVM參數(shù)、CPU、內(nèi)存、堆等信息的查看。
2、輔助進(jìn)行性能調(diào)優(yōu)。
3、輔助解決應(yīng)用運(yùn)行時(shí)的一些問題,比如:OutOfMemoryError、內(nèi)存泄漏、線程死鎖、鎖爭用、Java進(jìn)程消耗CPU過高等等。
jps:虛擬機(jī)進(jìn)程狀況工具
jps(JVM Process Status Tool)可以列出正在運(yùn)行的虛擬機(jī)進(jìn)程,并顯示虛擬機(jī)執(zhí)行主類(Main Class,main()函數(shù)所在的類)名稱以及這些進(jìn)程的本地虛擬機(jī)唯一ID(Local Virtual Machine Identifier,LVMID),即進(jìn)程ID。
jps命令格式
jps [options] [hostid]
參數(shù):
-q:只輸出LVMID(進(jìn)程id),省略主類的名稱。
-m:數(shù)據(jù)虛擬機(jī)進(jìn)程啟動(dòng)時(shí)傳遞給主類main()函數(shù)的參數(shù)。
-l:輸出主類的全名,如果進(jìn)程執(zhí)行的是Jar包,輸出Jar路徑。
-v:數(shù)據(jù)虛擬機(jī)進(jìn)程啟動(dòng)時(shí)JVM參數(shù)。
命令格式的各種參數(shù)的含義就不再解釋,主要介紹一下常見的用法,有想深入了解的去看上面地址的官方文檔
jps可以通過RMI(Remote Method Invocation,遠(yuǎn)程方法調(diào)用)協(xié)議查詢開啟了RMI服務(wù)的遠(yuǎn)程虛擬機(jī)進(jìn)程狀態(tài),hostid為RMI注冊表中注冊的主機(jī)名。
不指定hostid就默認(rèn)為當(dāng)前主機(jī)或服務(wù)器。
jinfo:Java配置信息工具
jinfo(Configuration Info for Java)的作用是實(shí)時(shí)地查看和調(diào)整虛擬機(jī)各項(xiàng)參數(shù)。 使用jps命令的-v參數(shù)可以查看虛擬機(jī)啟動(dòng)時(shí)顯式指定的參數(shù)列表,但如果想知道未被顯式指定的參數(shù)的系統(tǒng)默認(rèn)值,除了去找資料外,就只能使用jinfo的-flag選項(xiàng)進(jìn)行查詢了(如果只限于JDK 1.6或以上版本的話,使用java-XX:+PrintFlagsFinal查看參數(shù)默認(rèn)值也是一個(gè)很好的選擇)
jinfo 命令格式
jinfo [ option ] pid
參數(shù):
-v:查看虛擬機(jī)啟動(dòng)時(shí)顯式指定的參數(shù)列表。
-flag name:打印指定java虛擬機(jī)的參數(shù)值。
-flag name=value:修改一部分運(yùn)行期可修改的虛擬機(jī)參數(shù)值。
-flag [+|-]name:設(shè)置或取消指定java虛擬機(jī)參數(shù)的布爾值。
jstack:Java堆棧跟蹤工具
jstack(Stack Trace for Java)命令用于生成虛擬機(jī)當(dāng)前時(shí)刻的線程快照(一般稱為threaddump或者javacore文件),即查看某個(gè)Java進(jìn)程內(nèi)的線程堆棧信息。
線程快照就是當(dāng)前虛擬機(jī)內(nèi)每一條線程正在執(zhí)行的方法堆棧的集合,生成線程快照的主要目的是定位線程出現(xiàn)長時(shí)間停頓的原因,如線程間死鎖、 死循環(huán)、 請求外部資源導(dǎo)致的長時(shí)間等待等都是導(dǎo)致線程長時(shí)間停頓的常見原因。 線程出現(xiàn)停頓的時(shí)候通過jstack來查看各個(gè)線程的調(diào)用堆棧,就可以知道沒有響應(yīng)的線程到底在后臺(tái)做些什么事情,或者等待著什么資源。
jstack命令格式
jstack [ options ] pid
參數(shù):
-F:當(dāng)正常輸出的請求不被響應(yīng)時(shí),強(qiáng)制輸出線程堆棧。
-l:除了堆棧外,顯示關(guān)于鎖的附加信息。
-m:顯示本地方法的堆棧(C/C++)。
jmap:Java內(nèi)存映像工具
jmap(Memory Map for Java)命令用于生成堆轉(zhuǎn)儲(chǔ)快照(一般稱為heapdump或dump文件)。 如果不使用jmap命令,要想獲取Java堆轉(zhuǎn)儲(chǔ)快照,還有一些比較“暴力”的手段:譬如-XX:+HeapDumpOnOutOfMemoryError參數(shù),可以讓虛擬機(jī)在OOM異常出
現(xiàn)之后自動(dòng)生成dump文件,通過-XX:+HeapDumpOnCtrlBreak參數(shù)則可以使用[Ctrl]+[Break]鍵讓虛擬機(jī)生成dump文件,又或者在Linux系統(tǒng)下通過Kill-3命令發(fā)送進(jìn)程退出信號(hào)“嚇?!币幌绿摂M機(jī),也能拿到dump文件。
jmap命令格式
jmap [ options ] pid
參數(shù):
-dump:生成Java堆轉(zhuǎn)儲(chǔ)快照。格式為: -dump:[live,]format=b,file=<filename>,其中l(wèi)ive子參數(shù)說明是否只dump出存活的對(duì)象。
-heap:顯示java堆詳細(xì)信息,如使用哪種回收器,參數(shù)配置,分帶狀況等。只在Linux/Solaris平臺(tái)下有效。
-histo:顯示堆中對(duì)象統(tǒng)計(jì)信息,包括類,實(shí)例數(shù)量,合計(jì)容量。
-F:當(dāng)虛擬機(jī)進(jìn)程對(duì)-dump選項(xiàng)沒有響應(yīng)時(shí),可使用這個(gè)選項(xiàng)強(qiáng)制生成dump快照。只在Linux/Solaris平臺(tái)下有效。
jstat:虛擬機(jī)統(tǒng)計(jì)信息監(jiān)視工具
jstat(JVM Statistics Monitoring Tool)是用于監(jiān)視虛擬機(jī)各種運(yùn)行狀態(tài)信息的命令行工具。 它可以顯示本地或者遠(yuǎn)程虛擬機(jī)進(jìn)程中的類裝載、 內(nèi)存、 垃圾收集、 JIT編譯等運(yùn)行數(shù)據(jù),在沒有GUI圖形界面,只提供了純文本控制臺(tái)環(huán)境的服務(wù)器上,它將是運(yùn)行期定位虛擬機(jī)性能問題的首選工具。
jstat命令格式
jstat [ generalOption | outputOptions vmid [ interval[s|ms] [ count ] ]
參數(shù):
-class:監(jiān)視類裝載,卸載數(shù)量,總空間以及類裝載鎖消耗的時(shí)間。
-gc:監(jiān)視Java堆狀況,包括Eden區(qū),兩個(gè)survivor區(qū),老年代,永久代的容量,已用空間,GC時(shí)間合計(jì)等信息。
-gcutil:監(jiān)視內(nèi)容與-gc基本相同,但輸出主要關(guān)注已使用空間占總空間的百分比。
-gcnew:監(jiān)視新生代GC狀況。
-gcold:監(jiān)視老年代GC狀況。
-compiler:輸出JIT編譯器編譯過的方法,耗時(shí)等信息。
-printcompilation:輸出已經(jīng)被JIT編譯的方法。
jstatd:即虛擬機(jī)的jstat守護(hù)進(jìn)程
jstatd,即虛擬機(jī)的jstat守護(hù)進(jìn)程,主要用于監(jiān)控JVM的創(chuàng)建與終止,并提供一個(gè)接口允許遠(yuǎn)程監(jiān)控工具依附到在本地主機(jī)上運(yùn)行的JVM。
jstatd工具是一個(gè)RMI服務(wù)器應(yīng)用程序,主要用于監(jiān)控HotSpot Java 虛擬機(jī)的創(chuàng)建與終止,并提供一個(gè)接口以允許遠(yuǎn)程監(jiān)控工具附加到本地主機(jī)上運(yùn)行的JVM上。
jstatd服務(wù)器需要在本地主機(jī)上存在一個(gè)RMI注冊表。jstatd服務(wù)器將嘗試在默認(rèn)端口或-p port選項(xiàng)指定的端口附加到該RMI注冊表上。如果RMI注冊表不存在,jstatd應(yīng)用程序?qū)?huì)自動(dòng)創(chuàng)建一個(gè),并綁定到-p port選項(xiàng)指定的端口上,如果省略了-p port選項(xiàng),則綁定到默認(rèn)的RMI注冊表端口。你可以通過指定-nr選項(xiàng)來抑制內(nèi)部RMI注冊表的創(chuàng)建。
注意:此工具是不受支持的,并且無法確定在未來版本的JDK中是否可用。目前,此工具不適用于Windows 98和Windows ME平臺(tái)。
jstatd命令格式
jstatd [ options ]
參數(shù):
-nr:當(dāng)找不到現(xiàn)有的RMI注冊表時(shí),不嘗試使用jstatd進(jìn)程創(chuàng)建一個(gè)內(nèi)部的RMI注冊表。
-p port:在指定的端口查找RMI注冊表。如果沒有找到,并且沒有指定-nr選項(xiàng),則在該端口自行創(chuàng)建一個(gè)內(nèi)部的RMI注冊表。
-n rminame:RMI注冊表中綁定的RMI遠(yuǎn)程對(duì)象的名稱。默認(rèn)的名稱為JStatRemoteHost。如果多個(gè)jstatd服務(wù)器在同一主機(jī)上運(yùn)行,你可以通過指定該選項(xiàng)來讓每個(gè)服務(wù)器導(dǎo)出的RMI對(duì)象具有唯一的名稱。不管如何,這樣做需要將唯一的服務(wù)器名稱包含進(jìn)監(jiān)控客戶端的hostid和vmid字符串中。
-Joption:將選項(xiàng)參數(shù)傳遞給被javac調(diào)用的java啟動(dòng)程序。例如,-J-Xms48m設(shè)置啟動(dòng)內(nèi)存為48 MB。使用-J將選項(xiàng)參數(shù)傳遞給執(zhí)行Java應(yīng)用程序的底層虛擬機(jī),這是一種常見慣例。
jcmd:JVM診斷命令行工具
JDK7 update 4,新增了一個(gè)jcmd診斷命令行工具,它是一個(gè)多功能的工具,將診斷命令請求發(fā)送到正在運(yùn)行的Java虛擬機(jī),可以導(dǎo)出堆棧,查看jvm進(jìn)程,導(dǎo)出線程信息,執(zhí)行GC等。
jcmd沒有提供遠(yuǎn)程方法方式,只能查看本地的jvm信息:
jcmd <pid | main class> <command ...|PerfCounter.print|-f file>
參數(shù)含義:
jcmd PID VM.uptime:查看 JVM 的啟動(dòng)時(shí)長。
jcmd PID GC.class_histogram:查看 JVM 的類信息,這個(gè)可以查看每個(gè)類的實(shí)例數(shù)量和占用空間大小。
jcmd PID Thread.print:查看 JVM 的Thread Dump。
jcmd PID GC.heap_dump FILE_NAME:查看 JVM 的Heap Dump,注意,如果只指定文件名,默認(rèn)會(huì)生成在啟動(dòng) JVM 的目錄里。
jcmd PID VM.system_properties:查看 JVM 的屬性信息。
jcmd PID VM.flags:查看 JVM 的啟動(dòng)參數(shù),注意,可以看到 -X 和 -XX 的參數(shù)信息。
jcmd PID VM.command_line:查看 JVM 的啟動(dòng)命令行。
jcmd PID GC.run_finalization:對(duì) JVM 執(zhí)行 java.lang.System.runFinalization(),盡量b別去調(diào)用這個(gè)對(duì)象的finalize方法。
jcmd PID GC.run:對(duì) JVM 執(zhí)行 java.lang.System.gc(),告訴垃圾收集器打算進(jìn)行垃圾收集,而垃圾收集器進(jìn)不進(jìn)行收集是不確定的。
jcmd PID PerfCounter.print:查看 JVM 的性能。
JConsole:基于JMX的可視化監(jiān)視、管理工具
Jconsole (Java Monitoring and Management Console),JDK自帶的,一種基于JMX的可視化監(jiān)視、管理工具。
可以在系統(tǒng)有一定負(fù)荷的情況下使用;對(duì)垃圾回收算法有很詳細(xì)的跟蹤。
jconsole [ -interval=n ] [ -notile ] [ -pluginpath <path> ] [ -version ] [ connection ... ]
-interval:將更新間隔設(shè)置為 n 秒 (默認(rèn)值為 4 秒)
-notile:初始不平鋪窗口 (對(duì)于兩個(gè)或多個(gè)連接)
-pluginpath:指定 jconsole 用于查找插件的路徑
-version:輸出程序版本
connection = pid || host:port || JMX URL (service:jmx:<協(xié)議>://...)
pid 目標(biāo)進(jìn)程的進(jìn)程 ID
host 遠(yuǎn)程主機(jī)名或 IP 地址
port 遠(yuǎn)程連接的端口號(hào)
-J 指定運(yùn)行 jconsole 的 Java 虛擬機(jī)的輸入?yún)?shù)
執(zhí)行命令后,打開新建連接窗口,有兩種
- 1)本地進(jìn)程
- 2)遠(yuǎn)程進(jìn)程

1、概述
顯示有關(guān)Java VM和監(jiān)視值的概述信息,包括CPU使用情況,內(nèi)存使用情況,線程計(jì)數(shù)以及Java VM中加載的類的圖形監(jiān)視信息

2、內(nèi)存
顯示有關(guān)內(nèi)存消耗和內(nèi)存池的信息

“內(nèi)存”選項(xiàng)卡具有“執(zhí)行GC”按鈕,可以隨時(shí)單擊該按鈕以執(zhí)行垃圾回收。
該圖表顯示了Java VM隨時(shí)間的內(nèi)存使用情況,堆和非堆內(nèi)存以及特定內(nèi)存池的內(nèi)存使用情況。
Java VM管理兩種內(nèi)存:堆內(nèi)存和非堆內(nèi)存,這兩種內(nèi)存都是在Java VM啟動(dòng)時(shí)創(chuàng)建的。
- 1)堆內(nèi)存是運(yùn)行時(shí)數(shù)據(jù)區(qū),Java VM從中為所有類實(shí)例和數(shù)組分配內(nèi)存。堆可以是固定的或可變的大小。垃圾收集器是一個(gè)自動(dòng)內(nèi)存管理系統(tǒng),可回收對(duì)象的堆內(nèi)存。
- A.Eden Space:
伊甸區(qū),對(duì)象被創(chuàng)建的時(shí)候首先放到Eden Space,進(jìn)行垃圾回收后,不能被回收的對(duì)象被放入到空的Survivor區(qū)域 - B.Survivor Space:
幸存者區(qū),用于保存在eden space內(nèi)存區(qū)域中經(jīng)過垃圾回收后沒有被回收的對(duì)象
Survivor Space分為兩個(gè)空間大小一樣的區(qū)域,分別是To Survivor和From Survivor,并且始終保持一個(gè)Survivor是空的
- A.Eden Space:
Eden Space和Survivor Space都屬于新生代
對(duì)新生代 進(jìn)行垃圾回收被稱為Minor GC(或Young GC),每一次Minor GC后留下來的對(duì)象age(就是用來判斷對(duì)象是否進(jìn)入老年的標(biāo)志)加1
* C.Old Gen:
老年代,用于存放新生代中經(jīng)過多次垃圾回收仍然存活的對(duì)象,也有可能是新生代分配不了內(nèi)存的大對(duì)象會(huì)直接進(jìn)入老年代。
經(jīng)過多次垃圾回收都沒有被回收的對(duì)象,這些對(duì)象的age已經(jīng)足夠old了,就會(huì)放入到老年代。
當(dāng)老年代被放滿之后,虛擬機(jī)會(huì)進(jìn)行垃圾回收,稱之為Major GC。由于Major GC除并發(fā)GC外均需對(duì)整個(gè)堆進(jìn)行掃描和回收,因此又稱為Full GC
堆內(nèi)存默認(rèn)為物理內(nèi)存的1/64(<1GB);默認(rèn)空余堆內(nèi)存小于40%時(shí),JVM就會(huì)增大堆直到-Xmx的最大限制,可以通過MinHeapFreeRatio參數(shù)進(jìn)行調(diào)整;默認(rèn)空余堆內(nèi)存大于70%時(shí),JVM會(huì)減少堆直到-Xms的最小限制,可以通過MaxHeapFreeRatio參數(shù)進(jìn)行調(diào)整。
- 2)非堆內(nèi)存包括在Java VM的內(nèi)部處理或優(yōu)化所需的所有線程和內(nèi)存之間共享的方法區(qū)域。
它存儲(chǔ)每類結(jié)構(gòu),例如運(yùn)行時(shí)常量池,字段和方法數(shù)據(jù),以及方法和構(gòu)造函數(shù)的代碼。
方法區(qū)域在邏輯上是堆的一部分,但是根據(jù)實(shí)現(xiàn),Java VM可能不會(huì)垃圾收集或壓縮它。
與堆存儲(chǔ)器一樣,方法區(qū)域可以是固定的或可變的大小。方法區(qū)域的內(nèi)存不需要是連續(xù)的。
* A.Metaspace:
元空間,是方法區(qū)的在HotSpot jvm 中的實(shí)現(xiàn),方法區(qū)主要用于存儲(chǔ)類的信息、常量池、方法數(shù)據(jù)、方法代碼等。方法區(qū)邏輯上屬于堆的一部分,但是為了與堆進(jìn)行區(qū)分,通常又叫“非堆”。
* B.Code Cache:
HotSpot Java VM還包括代碼緩存,其中包含用于編譯和存儲(chǔ)本機(jī)代碼的內(nèi)存。
* C.Compressed Class Space:壓縮類空間
3、線程
顯示有關(guān)線程使用的信息

紅色:峰值線程數(shù),藍(lán)色:活動(dòng)線程數(shù)。
左下角的線程列表列出了所有活動(dòng)線程
單擊“線程”列表中的線程名稱,以顯示有關(guān)該線程的信息,包括線程名稱,狀態(tài)和堆棧跟蹤。
4、類監(jiān)控加載
顯示有關(guān)類加載的信息

紅線是加載的類的總數(shù)(包括隨后卸載的類),藍(lán)線是當(dāng)前加載的類的數(shù)量。
“詳細(xì)信息”部分顯示自Java VM啟動(dòng)以來加載的類的總數(shù),當(dāng)前加載的數(shù)量和卸載的數(shù)量。
通過選中右上角的復(fù)選框?qū)㈩惣虞d跟蹤設(shè)置為詳細(xì)輸出
5、VM信息
提供有關(guān)Java VM的信息

6、MBean
顯示了所有在platform. MBeanserver上注冊的MBeans的信息

左邊的樹形結(jié)構(gòu)顯示了所有的MBean
選擇了一個(gè)MBean之后,其屬性、操作、通知和其他信息會(huì)在右邊顯示
兩種遠(yuǎn)程連接方式
JMX連接可以查看:系統(tǒng)信息、CPU使用情況、線程多少、手動(dòng)執(zhí)行垃圾回收等比較偏于系統(tǒng)層面的信息。
jstatd連接方式可以提供:JVM內(nèi)存分布詳細(xì)信息、垃圾回收分布圖、線程詳細(xì)信息、甚至可以看到某個(gè)對(duì)象使用內(nèi)存的大小。
遠(yuǎn)程連接Tomcat
- 配置JMX的支持,需要在tomcat的catalina.sh里面添加一些設(shè)置:
修改Tomcat下的bin/catalina.sh文件,搜索 Execute The Requested Command ,在下方添加以下內(nèi)容(ip修改成自己的):
CATALINA_OPTS="$CATALINA_OPTS
-Dcom.sun.management.jmxremote=true
-Djava.rmi.server.hostname=10.1.1.52
-Dcom.sun.management.jmxremote.port=1099
-Dcom.sun.management.jmxremote.ssl=false
-Dcom.sun.management.jmxremote.authenticate=false"

需要開啟鑒權(quán)功能(用戶密碼登錄監(jiān)視),修改成以下內(nèi)容:
CATALINA_OPTS="$CATALINA_OPTS
-Dcom.sun.management.jmxremote=true
-Djava.rmi.server.hostname=10.1.1.52
-Dcom.sun.management.jmxremote.port=1099
-Dcom.sun.management.jmxremote.ssl=false
-Dcom.sun.management.jmxremote.authenticate=true
-Dcom.sun.management.jmxremote.password.file=../conf/jmxremote.password
-Dcom.sun.management.jmxremote.access.file=../conf/jmxremote.access"
server.hostname:ip
jmxremote.port:開啟jmx的端口
jmxremote.ssl:是否開啟ssl(false/true)
jmxremote.authenticate:是否開啟鑒權(quán)功能,賬號(hào)密碼遠(yuǎn)程監(jiān)控(false/true)
jmxremote.password.file:密碼文件路徑
jmxremote.access.file:權(quán)限文件路徑

創(chuàng)建文件
touch jmxremote.password jmxremote.access
在JAVA_HOME\jre\lib\management下有模板
jmxremote.password文件添加以下內(nèi)容:
#(123456、123456789為密碼)
monitorRole 123456
controlRole 123456789
jmxremote.access文件添加以下內(nèi)容:
monitorRole readonly
controlRole readwrite
新建完成這兩個(gè)文件要修改jmxremote.password的權(quán)限
#賦值權(quán)限
chmod 600 jmxremote.password
配置jstatd(jdk13):1、自定義一個(gè)statd.policy文件,添加:
grant codebase "jrt:/jdk.jstatd" {
permission java.security.AllPermission;
};
grant codebase "jrt:/jdk.internal.jvmstat" {
permission java.security.AllPermission;
};
然后在JDK_HOME/bin下面運(yùn)行jstatd,示例如:
./jstatd -J -Djava.rmi.server.hostname=192.168.1.102 -J -Djava.security.policy=java.policy=java.policy -p 1099 &
參考:
https://blog.csdn.net/zzti_erlie/article/details/86517158