從源碼角度深度分析JVM虛擬機監控工具

前言

上一篇文章JVM虛擬機性能監控與故障處理工具介紹了常用虛擬機監控工具的使用方法以及參數含義,這一篇就從源碼角度來看一下它們的內部構造。因爲筆者時間有限,目前爲止只看了jps、jstat、jstack的源碼,同時筆者也準備寫一個更方便於開發者調用的API,對其源碼進行了相應的改造,至於爲什麼改造後面看源碼的時候給大家講,最後API做出來了還希望大家多多支持哦~

如果讀者有興趣深入學習虛擬機監控相關的類庫,需要提示一下,jdk/lib下面的包是核心包,無論是你看源碼還是拓展類庫,都離不開他們,目前就筆者看的jps、jstat、jstack三個命令來說,需要把tools.jarsa-jdi.jar兩個包加入到項目中,其中tools.jar提供較多的命令式調用的類庫,也包括參數解析等,jps和jstat完全只用tools.jar就可以了,但是jstack必需sa-jdi.jar這個包,因爲其內部使用反射調用了這個包中的JStack類的main方法,如果不加入的話就會報異常。

在jar包中的文件都是class文件,你需要進行手動反編譯去看,或者你用idea工具編譯,這裏筆者是用的idea工具解析的。

因爲jstat和jstack命令較爲複雜,內容較多,一篇文章不足以講述,所以這裏以jps命令源碼解析爲主,另外兩個命令會說一些大體執行流程,不會系講

jps命令


在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述

看完jps執行函數之後最關心的就是如何獲取這些虛擬機實例的,筆者也很是好奇,於是去看了getMonitoredHost()這個方法。結果發現這些獲取虛擬機的信息都是通過System.getProperty()方法獲取的,這些都是從系統或虛擬機底層提供的實時數據,這些也是虛擬機的開發者爲了方便管理VM提供的一些數據信息,沒什麼好奇怪的。

在這裏插入圖片描述

jstat和jstack命令

jstat命令可以獲取很多虛擬機參數、類加載、gc、內存情況等等,jstack可以獲取各個線程的堆棧信息,這兩個命令相比於jps內部相對更加複雜,這裏篇幅原因就不詳細講述了。如果有興趣可以關注筆者開發的API(開發中),裏面會有一些代碼註釋,當然那是筆者改造之後的代碼,和源代碼有一些差別。

jstat命令因爲命令參數較多,而且返回的數據差別較大,所以它是將所有結果進行了Format處理,將結果包裝成OutputFormatter對象後統一輸出,在其內部是通過虛擬機全路徑打開一個輸出流(OutputStream),這些時實的信息都是從虛擬機按照特定的協議獲取數據。

jstack命令的構造則和前兩個有點不太,前兩個的相關處理類都是在tools.jar包中,而jstack則沒有,在tools包中的Jstack類實際上就只是一個外殼,沒有實際的含義,爲什麼這麼說呢?看下面這個圖就知道了

在這裏插入圖片描述
是不是恍然大悟?它實際上就是通過反射調用Hotspot包下面的Jstack類的方法,而這個類就在sa_jdi.jar包中,仔細去看裏面Jstack的執行函數體,它是通過Tool類註冊監視虛擬機的vmId,然後又跑一個多線程去依次遍歷被監視虛擬機的各個線程數據信息。

總結

通過看源碼還是有很多收穫的,設計者的代碼風格簡潔明瞭,很多是值的借鑑的。對於虛擬機的監控來講,或許只有通過虛擬機開發商提供的數據或管理接口才能獲取,畢竟這東西是別人開發的嘛,規則還得他們來制定。如果想自己寫監控工具要麼使用System的exec方法調用,但是這個方法有很大弊端,如果同時調用數量多了而且很不幸調用進程發生了阻塞,這樣容易造成內存衝爆,因爲它的原理實際上是調用系統的其他進程,也就是說它會開一個新的進程去執行,和在命令行執行是一樣的,這種開銷太大不推薦使用,在《深入理解Java虛擬機》第5章作者也有講到這個。最好的是使用提供的api或者在此基礎上進行改進,而tools這些命令類庫直接使用顯然是沒法的,比如上面看的jps命令,很多地方用到了System.exit(),而且輸出全都是寫死了的,用的System.out,想獲取內容只能通過控制檯,其他tools下面的所有工具類都是如此。所以最好的辦法就是重構它們啦,筆者也是初次寫虛擬機監控API,如果你對此有興趣歡迎和我交流。

歡迎關注作者的微信公衆號:北風IT之路

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章