簡書 占小狼,轉載請注明原創(chuàng)出處露该,謝謝睬棚!
當服務發(fā)生GC問題時,一般會使用jmap工具進行分析解幼,jmap工具很強大抑党,所以有必要了解它的方方面面。
jmap可以做什么撵摆?
1底靠、jmap -histo[:live] <pid>
通過histo選項,打印當前java堆中各個對象的數(shù)量特铝、大小暑中。
如果添加了live,只會打印活躍的對象鲫剿。
2鳄逾、jmap -dump:[live,]format=b,file=<filename> <pid>
通過-dump選項,把java堆中的對象dump到本地文件灵莲,然后使用MAT進行分析雕凹。
如果添加了live,只會dump活躍的對象政冻。
3枚抵、jmap -heap <pid>
通過-heap選項,打印java堆的配置情況和使用情況赠幕,還有使用的GC算法俄精。
4询筏、jmap -finalizerinfo <pid>
通過-finalizerinfo選項榕堰,打印那些正在等待執(zhí)行finalize方法的對象。
5嫌套、jmap -permstat <pid>
通過-permstat選項逆屡,打印java堆永久代的信息,包括class loader相關的信息,和interned Strings的信息踱讨。
jmap實現(xiàn)原理
通過jmap和jvm之間進行通信魏蔗,有兩種實現(xiàn)方式:attach 和 SA。
attach
attach方式痹筛,簡單來說就是客戶端和服務端之間的通信莺治,客戶端發(fā)送請求廓鞠,主要邏輯在服務端執(zhí)行,jmap相當于客戶端谣旁,JVM相當于服務端床佳。
在JVM中,有一個叫"Attach Listener"的線程榄审,專門負責監(jiān)聽attach的請求砌们,并執(zhí)行對應的操作。
比如現(xiàn)在執(zhí)行"jmap -histo:live 5409"搁进,一步一步的實現(xiàn)如下:
1浪感、在Jmap.java類的main函數(shù)中,對參數(shù)進行解析饼问。
2影兽、解析出來參數(shù)中有“-histo:live”,則執(zhí)行histo方法:
attach方法建立了jmap進程和JVM之間的socket連接匆瓜,建立過程可以查看笨神的文章JVM Attach機制實現(xiàn)赢笨,后續(xù)基于該連接進行通信。
因為命令行中添加了[:live]選項驮吱,這里的live參數(shù)是true茧妒。
再看看heapHisto方法
executeCommand方法基于之前的socket連接向JVM發(fā)送了一條"inspectheap"命令,當然了左冬,還有參數(shù)桐筏。
虛擬機的"Attach Listener"線程當發(fā)現(xiàn)有新的命令時,就拿出來處理它拇砰。
命令和具體的函數(shù)對應關系如下:
和"inspectheap"對應的是heap_inspection方法梅忌,實現(xiàn)如下:
live_objects_only的值取決于請求中是否有"-live",再jmap中除破,取決于是否有":live"牧氮,所以不管是不是添加了":live",都會有STW過程瑰枫,時間長短而已踱葛。
在VM_GC_HeapInspection的doit方法中
_full_gc的值就是live_objects_only,如果為true光坝,可能會執(zhí)行一次full gc尸诽,清空非活躍的對象,但是可能會因為GC locker盯另,導致跳過本次的GC性含。
"jmap -dump"實現(xiàn)的原理和"jmap -histo"類似,都是通過attach的方式實現(xiàn)鸳惯,
attach API的實現(xiàn)方式是:
1商蕴、客戶端連接到目標JVM叠萍,向其發(fā)出一個類似“inspectheap”命令;
2绪商、目標JVM接收到命令俭令,執(zhí)行JVM內相關函數(shù),將收集到的結果以文本形式返回部宿;
3抄腔、客戶端接收到返回的文本并將其顯示出來;
SA
假如執(zhí)行"jmap -heap 5409"理张,就不會使用attach方式實現(xiàn)了赫蛇。
在參數(shù)解析中,如果參數(shù)是"-heap|-heap:format=b|-permstat|-finalizerinfo"中的一種雾叭,或者添加了"-F"悟耘,比如"jmap -histo -F 5409",則使用SA的方式织狐。
SA方式暂幼,和attach方式不同的是,相關的主要邏輯都在SA中實現(xiàn)移迫,從JVM中獲取數(shù)據(jù)即可旺嬉。
可以大概看下"jmap -heap"的實現(xiàn),對應的實現(xiàn)類是"HeapSummary"厨埋,內部通過BugSpotAgent工具類attach到目標VM邪媳,更具體的底層細節(jié),可以參考HotSpot Serviceability Agent 實現(xiàn)淺析
執(zhí)行jmap -heap有些時候可能會導致進程變T荡陷,一般是有一個線程在等信號量雨效,這時會block住其它所有線程,可以執(zhí)行kill -CONT <pid>進行恢復废赞,不過還是強烈建議別執(zhí)行這個命令徽龟。