虛擬機(jī)系列:虛擬機(jī)圖形化監(jiān)控工具-VisualVM
時(shí)間:2023-06-27 23:09:02 | 來源:網(wǎng)站運(yùn)營(yíng)
時(shí)間:2023-06-27 23:09:02 來源:網(wǎng)站運(yùn)營(yíng)
虛擬機(jī)系列:虛擬機(jī)圖形化監(jiān)控工具-VisualVM:
VisualVM(All-in-One Java Troubleshooting Tool)是功能最強(qiáng)大的運(yùn)行監(jiān)視和故障處理程序之一,它集成了多種性能統(tǒng)計(jì)工具的功能,可以替代jstat,jmap,jstack,也可以替代JConsole的使用。VisualVM有一個(gè)很大的優(yōu)點(diǎn):不需要被監(jiān)視的程序基于特殊的Agent去運(yùn)行,因此它的通用性很強(qiáng),對(duì)應(yīng)用程序?qū)嶋H性能的影響也較小,使得它可以直接應(yīng)用在生產(chǎn)環(huán)境中。
還有一大特點(diǎn)就是支持插件擴(kuò)展,有了插件的擴(kuò)展能力,就可以支持更多的功能,例如
- 顯示虛擬機(jī)進(jìn)程以及進(jìn)程的配置、環(huán)境信息(jps、jinfo)。
- 監(jiān)視應(yīng)用程序的處理器、垃圾收集、堆、方法區(qū)以及線程的信息(jstat、jstack)。
- dump以及分析堆轉(zhuǎn)儲(chǔ)快照(jmap、jhat)。
- 方法級(jí)的程序運(yùn)行性能分析,找出被調(diào)用最多、運(yùn)行時(shí)間最長(zhǎng)的方法。
- 離線程序快照:收集程序的運(yùn)行時(shí)配置、線程dump、內(nèi)存dump等信息建立一個(gè)快照,可以將快照發(fā)送開發(fā)者處進(jìn)行Bug反饋。
打開并連接
程序是在%JAVA_HOME%/bin的目錄下,直接雙擊即可啟動(dòng)客戶端,如下圖
此監(jiān)控工具默認(rèn)的功能較少,我們首先要安裝一些插件,方便我們監(jiān)控使用,點(diǎn)擊
工具
->
插件
打開插件的安裝頁(yè)面,并選擇自己需要的插件下載即可,如下
如果下載不了,請(qǐng)重新設(shè)置
插件中心配置根據(jù)自己的jdk版本在插件中心頁(yè)面找到對(duì)應(yīng)版本的地址,然后點(diǎn)擊進(jìn)入,最上面的
Catalog URL就是需要的配置中心地址:
https://visualvm.github.io/pluginscenters.html和Jconsole一樣,有兩種連接方式,一個(gè)是
本地連接,另一個(gè)是
遠(yuǎn)程連接本地連接:在控制臺(tái)可以看到本地出現(xiàn)的Java程序,直接雙擊或者右鍵打開 即可
遠(yuǎn)程連接:右鍵選擇
JMX連接,輸入連接信息IP:端口 點(diǎn)擊確定即可(本地節(jié)點(diǎn)會(huì)下出現(xiàn)一個(gè)jmx的圖標(biāo))前提是Java程序已經(jīng)添加以下參數(shù)啟動(dòng)
-Djava.rmi.server.hostname=127.0.0.1 //遠(yuǎn)程服務(wù)器的IP(本地可訪問)-Dcom.sun.management.imxremote -Dcom.sun.management.jmxremote.port=5555 // 遠(yuǎn)程服務(wù)器的端口(隨便定一個(gè),用于JMX管理該進(jìn)程)-Dcom.sun.management.jmxremote.authenticate=false // 是否驗(yàn)證(true的話需要配置密碼,自行百度吧)-Dcom.sun.management.jmxremote.ssl=false //ssl控制
如下兩個(gè)相同的應(yīng)用,一個(gè)是遠(yuǎn)程的連接,一個(gè)是本地的連接
應(yīng)用概述
這個(gè)
概述tab可以查看應(yīng)用的基本信息,例如java版本,主類,jvm參數(shù)(啟動(dòng)參數(shù)),系統(tǒng)屬性等
監(jiān)控信息
切換到
監(jiān)控tab 可以看到應(yīng)用的CPU,堆,元空間,類加載以及線程數(shù)的總體變化情況。頁(yè)面上還有兩個(gè)按鈕
執(zhí)行垃圾回收和
堆dump,操作按鈕可以立即執(zhí)行full gc(下圖堆大小減少)和生存堆快照。
線程分析
切換到
線程tab可以看到應(yīng)用中線程的信息,展現(xiàn)了線程的數(shù)量,右上角有個(gè)
線程Dump的按鈕,可以下載當(dāng)前所有現(xiàn)場(chǎng)的堆棧信息(相當(dāng)于jstack)。最下面還可以點(diǎn)擊每個(gè)線程,展示每個(gè)線程的信息,如果存在死鎖,會(huì)以紅色字體給出提示,如下圖
點(diǎn)擊線程Dump按鈕,獲取的堆棧信息,例如其中的死鎖信息,可以直接看到發(fā)生死鎖的具體位置
性能分析
切換到
抽樣器tab 可以看到共有CPU和內(nèi)存兩個(gè)性能采樣器,可以實(shí)時(shí)的監(jiān)控對(duì)應(yīng)應(yīng)用的CPU和內(nèi)存變化。CPU采樣器可以將CPU占用時(shí)間定位到具體方法,而內(nèi)存采樣器可以查看當(dāng)前應(yīng)用的堆信息,根據(jù)頁(yè)面
CPU和
內(nèi)存的按鈕選擇。
CPU采樣
下面這個(gè)例子讓程序占用CPU,看看監(jiān)控上是什么樣子
public class Test2 { public static void main(String[] args) throws InterruptedException { fullCpu(); } private static void fullCpu() throws InterruptedException { long startTime = 0; while (true) { startTime = System.currentTimeMillis(); while (System.currentTimeMillis() - startTime < 8) { } Thread.sleep(2); } }}
如下圖Test2.fullCpu()方法占用了大量的CPU時(shí)間,而其他方法就比較空閑。通過這個(gè)tab,我們可以很快速方便的定位到應(yīng)用中最耗資源的方法并解決。(而線程CPU時(shí)間,可以看到是根據(jù)CPU資源消耗大小對(duì)線程的排序)
內(nèi)存采樣
通過內(nèi)存采樣可以實(shí)時(shí)查看每個(gè)類內(nèi)存占用情況,在應(yīng)用運(yùn)行的過程中,visual VM實(shí)時(shí)更新數(shù)據(jù),動(dòng)態(tài)的顯示各個(gè)class內(nèi)存占用的大小,同時(shí)還可以查看每個(gè)線程分配的內(nèi)存大小。如下圖
GC信息
切換到
Visual GC的tab,可以看到堆的信息變化的圖表,包括Metaspace,老年代,新生代的伊甸區(qū),S0區(qū)和S1區(qū)的實(shí)時(shí)動(dòng)態(tài)數(shù)據(jù)。
Btrace動(dòng)態(tài)跟蹤
Btrace的作用是使在不停機(jī)的情況下,通過Hotspot虛擬機(jī)的Instrument功能動(dòng)態(tài)的加入調(diào)試代碼??梢愿欀付ǖ姆椒ㄕ{(diào)用,構(gòu)造函數(shù)以及系統(tǒng)內(nèi)存等信息,我感覺主要的意義在于如當(dāng)程序出現(xiàn)問題時(shí),排查錯(cuò)誤的一些必要信息時(shí) (譬如方法參數(shù)、返回值等),在開發(fā)時(shí)并沒有打印到日志之中以至于不得不停掉服務(wù)時(shí),都可以通過調(diào)試增量來加入日志代碼以解決問題。
可以說Btrace是檢查和解決線上問題的大招,不用重啟服務(wù),通過腳本命令執(zhí)行。
安裝Btrace插件之后在對(duì)應(yīng)的應(yīng)用右鍵選擇
Trace Application
就會(huì)進(jìn)入對(duì)應(yīng)的操作面板,一個(gè)代碼輸入的控制頁(yè)面。
這個(gè)舉個(gè)例子:已經(jīng)上線的代碼出現(xiàn)空指針,但是對(duì)應(yīng)直接看不出具體原因,需要輸出一些額外信息輔助判斷,或者需要在日志中輸出一些額外信息。
線上代碼如下
public class Test2 { public static int add(int a, int b) { return a + b; } public static void main(String[] args) throws InterruptedException { while (true){ int a = (int) Math.round(Math.random() * 100); int b = (int) Math.round(Math.random() * 100); add(a,b); Thread.sleep(2000); } }}
現(xiàn)在上面的代碼已經(jīng)在線上運(yùn)行了,但是我現(xiàn)在需要知道a,b兩個(gè)隨機(jī)參數(shù)的具體值是什么,可以打開Btrace的代碼界面,然后填充TracingScript即可,代碼如下
/* BTrace Script Template */import com.sun.btrace.annotations.*;import static com.sun.btrace.BTraceUtils.*;?@BTracepublic class TracingScript { /* put your code here */@OnMethod(clazz="/.*Test2", // 監(jiān)控以Test2結(jié)尾的類 method="add", location=@Location(Kind.RETURN)) public static void func(int a,int b, @Return int result){ println("開始==============="); jstack(); println(strcat("方法參數(shù)A:",str(a))); println(strcat("方法參數(shù)B:",str(b))); println(strcat("方法結(jié)果:",str(result))); }}
@OnMethod中參數(shù)的clazz需要控制的類,method是類中的方法,location中的Kind.RETURN是指方法結(jié)束后輸出信息以及堆棧信息。想深入了解這三種參數(shù)的具體使用方法請(qǐng)自行百度:“Btrace Java”
然后點(diǎn)擊Start按鈕就會(huì)開始執(zhí)行,看到控制臺(tái)輸出的信息,如圖
BTrace的用途很廣泛,打印調(diào)用堆棧、參數(shù)、返回值只是它最基礎(chǔ)的使用形式。還可以實(shí)現(xiàn)的功能包括
監(jiān)控指定函數(shù)的耗時(shí)
,
獲取任意行代碼信息
,
腳本定時(shí)
,
獲取類的屬性
等。
在官網(wǎng)上有使用BTrace進(jìn)行性能監(jiān)視、定位連接泄漏、內(nèi)存泄漏、解決多線程競(jìng)爭(zhēng)問題等的使用案例,有興趣的讀者可以去網(wǎng)上了解相關(guān)信息。
官網(wǎng)在此:
https://github.com/btraceio/btrace
我是阿紀(jì),用輸出倒逼輸入而持續(xù)學(xué)習(xí),持續(xù)分享技術(shù)系列文章,以及全網(wǎng)值得收藏好文,歡迎主頁(yè)關(guān)注公眾號(hào),做一個(gè)持續(xù)成長(zhǎng)的技術(shù)人。 除了Java虛擬機(jī)相關(guān)的系列內(nèi)容 還有MySQL高級(jí)相關(guān)更多內(nèi)容,如鎖,MVCC,讀寫分離,分庫(kù)分表等還在持續(xù)更新中,如果有想了解的內(nèi)容也可以給我留言,歡迎關(guān)注催更。
所有內(nèi)容首發(fā)于個(gè)人網(wǎng)站:紀(jì)先生進(jìn)階指南
歷史文章:- 虛擬機(jī)系列:JVM 運(yùn)行時(shí)堆內(nèi)存如何分代
- 虛擬機(jī)系列:jvm中的垃圾回收算法
- 虛擬機(jī)系列:jvm運(yùn)行時(shí)數(shù)據(jù)區(qū)
- 虛擬機(jī)系列:對(duì)象的創(chuàng)建,內(nèi)存布局和訪問定位
- 虛擬機(jī)系列:jvm中的垃圾收集器
- 虛擬機(jī)系列:jvm中的內(nèi)存分配
- 虛擬機(jī)系列:搞懂虛擬機(jī)日志和日志參數(shù)
- 虛擬機(jī)系列:虛擬機(jī)性能監(jiān)控基礎(chǔ)工具
- 虛擬機(jī)系列:虛擬機(jī)性能監(jiān)控基礎(chǔ)工具-jstat
- 虛擬機(jī)系列:虛擬機(jī)性能監(jiān)控可視化工具-JConsole