jmap命令的實(shí)現(xiàn)原理解析

簡(jiǎn)書 占小狼,轉(zhuǎn)載請(qǐng)注明原創(chuàng)出處,謝謝!

當(dāng)服務(wù)發(fā)生GC問題時(shí),一般會(huì)使用jmap工具進(jìn)行分析,jmap工具很強(qiáng)大,所以有必要了解它的方方面面。

jmap可以做什么?

1、jmap -histo[:live] <pid>

通過histo選項(xiàng),打印當(dāng)前java堆中各個(gè)對(duì)象的數(shù)量、大小。
如果添加了live,只會(huì)打印活躍的對(duì)象。

2、jmap -dump:[live,]format=b,file=<filename> <pid>

通過-dump選項(xiàng),把java堆中的對(duì)象dump到本地文件,然后使用MAT進(jìn)行分析。
如果添加了live,只會(huì)dump活躍的對(duì)象。

3、jmap -heap <pid>

通過-heap選項(xiàng),打印java堆的配置情況和使用情況,還有使用的GC算法。

4、jmap -finalizerinfo <pid>

通過-finalizerinfo選項(xiàng),打印那些正在等待執(zhí)行finalize方法的對(duì)象。

5、jmap -permstat <pid>

通過-permstat選項(xiàng),打印java堆永久代的信息,包括class loader相關(guān)的信息,和interned Strings的信息。

jmap實(shí)現(xiàn)原理

通過jmap和jvm之間進(jìn)行通信,有兩種實(shí)現(xiàn)方式:attach 和 SA。

attach

attach方式,簡(jiǎn)單來(lái)說就是客戶端和服務(wù)端之間的通信,客戶端發(fā)送請(qǐng)求,主要邏輯在服務(wù)端執(zhí)行,jmap相當(dāng)于客戶端,JVM相當(dāng)于服務(wù)端。

在JVM中,有一個(gè)叫"Attach Listener"的線程,專門負(fù)責(zé)監(jiān)聽attach的請(qǐng)求,并執(zhí)行對(duì)應(yīng)的操作。

比如現(xiàn)在執(zhí)行"jmap -histo:live 5409",一步一步的實(shí)現(xiàn)如下:
1、在Jmap.java類的main函數(shù)中,對(duì)參數(shù)進(jìn)行解析。
2、解析出來(lái)參數(shù)中有“-histo:live”,則執(zhí)行histo方法:

attach方法建立了jmap進(jìn)程和JVM之間的socket連接,建立過程可以查看笨神的文章JVM Attach機(jī)制實(shí)現(xiàn),后續(xù)基于該連接進(jìn)行通信。

因?yàn)槊钚兄刑砑恿薣:live]選項(xiàng),這里的live參數(shù)是true。

再看看heapHisto方法

executeCommand方法基于之前的socket連接向JVM發(fā)送了一條"inspectheap"命令,當(dāng)然了,還有參數(shù)。

虛擬機(jī)的"Attach Listener"線程當(dāng)發(fā)現(xiàn)有新的命令時(shí),就拿出來(lái)處理它。

命令和具體的函數(shù)對(duì)應(yīng)關(guān)系如下:

和"inspectheap"對(duì)應(yīng)的是heap_inspection方法,實(shí)現(xiàn)如下:

live_objects_only的值取決于請(qǐng)求中是否有"-live",再jmap中,取決于是否有":live",所以不管是不是添加了":live",都會(huì)有STW過程,時(shí)間長(zhǎng)短而已。

在VM_GC_HeapInspection的doit方法中

_full_gc的值就是live_objects_only,如果為true,可能會(huì)執(zhí)行一次full gc,清空非活躍的對(duì)象,但是可能會(huì)因?yàn)镚C locker,導(dǎo)致跳過本次的GC。

"jmap -dump"實(shí)現(xiàn)的原理和"jmap -histo"類似,都是通過attach的方式實(shí)現(xiàn),
attach API的實(shí)現(xiàn)方式是:
1、客戶端連接到目標(biāo)JVM,向其發(fā)出一個(gè)類似“inspectheap”命令;
2、目標(biāo)JVM接收到命令,執(zhí)行JVM內(nèi)相關(guān)函數(shù),將收集到的結(jié)果以文本形式返回;
3、客戶端接收到返回的文本并將其顯示出來(lái);

SA

假如執(zhí)行"jmap -heap 5409",就不會(huì)使用attach方式實(shí)現(xiàn)了。

在參數(shù)解析中,如果參數(shù)是"-heap|-heap:format=b|-permstat|-finalizerinfo"中的一種,或者添加了"-F",比如"jmap -histo -F 5409",則使用SA的方式。

SA方式,和attach方式不同的是,相關(guān)的主要邏輯都在SA中實(shí)現(xiàn),從JVM中獲取數(shù)據(jù)即可。

可以大概看下"jmap -heap"的實(shí)現(xiàn),對(duì)應(yīng)的實(shí)現(xiàn)類是"HeapSummary",內(nèi)部通過BugSpotAgent工具類attach到目標(biāo)VM,更具體的底層細(xì)節(jié),可以參考HotSpot Serviceability Agent 實(shí)現(xiàn)淺析

執(zhí)行jmap -heap有些時(shí)候可能會(huì)導(dǎo)致進(jìn)程變T,一般是有一個(gè)線程在等信號(hào)量,這時(shí)會(huì)block住其它所有線程,可以執(zhí)行kill -CONT <pid>進(jìn)行恢復(fù),不過還是強(qiáng)烈建議別執(zhí)行這個(gè)命令。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容