Arthas是阿里開源的Java診斷工具坏逢,相比JDK內(nèi)置的診斷工具,要更人性化妙黍,并且功能強(qiáng)大悴侵,可以實現(xiàn)許多問題的一鍵定位,而且可以一鍵反編譯類查看源碼拭嫁,甚至是直接進(jìn)行生產(chǎn)代碼熱修復(fù)可免,實現(xiàn)在一個工具內(nèi)快速定位和修復(fù)問題的一站式服務(wù)。今天做粤,我就帶你使用Arthas定位一個CPU使用高的問題浇借,系統(tǒng)學(xué)習(xí)下這個工具的使用。
首先怕品,下載并啟動Arthas:
curl -O https://alibaba.github.io/arthas/arthas-boot.jar
java -jar arthas-boot.jar
dashboard命令用于整體展示進(jìn)程所有線程妇垢、內(nèi)存、GC等情況肉康,其輸出如下:
可以看到闯估,CPU高并不是GC引起的,占用CPU較多的線程有8個吼和,其中7個是ForkJoinPool.commonPool涨薪。ForkJoinPool.commonPool是并行流默認(rèn)使用的線程池。所以纹安,此次CPU高的問題尤辱,應(yīng)該出現(xiàn)在某段并行流的代碼上砂豌。
接下來,要查看最繁忙的線程在執(zhí)行的線程棧光督,可以使用thread?-n命令阳距。這里,我們查看下最忙的8個線程:
可以看到结借,由于這些線程都在處理MD5的操作筐摘,所以占用了大量CPU資源。我們希望分析出代碼中哪些邏輯可能會執(zhí)行這個操作船老,所以需要從方法棧上找出我們自己寫的類咖熟,并重點(diǎn)關(guān)注。由于主線程也參與了ForkJoinPool的任務(wù)處理柳畔,因此我們可以通過主線程的椻晒埽看到需要重點(diǎn)關(guān)注
org.geekbang.time.commonmistakes.troubleshootingtools.highcpu.HighCPUApplication類的doTask方法。接下來薪韩,使用jad命令直接對HighCPUApplication類反編譯:
jad org.geekbang.time.commonmistakes.troubleshootingtools.highcpu.HighCPUApplication
可以看到确沸,調(diào)用路徑是main->task()->doTask(),當(dāng)doTask方法接收到的int參數(shù)等于某個常量的時候俘陷,會進(jìn)行1萬次的MD5操作罗捎,這就是耗費(fèi)CPU的來源。那么拉盾,這個魔法值到底是多少呢桨菜?
你可能想到了,通過jad命令繼續(xù)查看User類即可捉偏。這里因為是Demo倒得,所以我沒有給出很復(fù)雜的邏輯。在業(yè)務(wù)邏輯很復(fù)雜的代碼中告私,判斷邏輯不可能這么直白屎暇,我們可能還需要分析出doTask的“慢”會慢在什么入?yún)⑸稀?/p>
這時,我們可以使用watch命令來觀察方法入?yún)⒆に凇H缦旅罡浚硎拘枰O(jiān)控耗時超過100毫秒的doTask方法的入?yún)ⅲ⑶逸敵鋈雲(yún)⑹癯牛归_2層入?yún)?shù):
最后挤巡,我們使用ognl命令來運(yùn)行一個表達(dá)式,直接查詢User類的ADMIN_ID靜態(tài)字段來驗證是不是這樣酷麦,得到的結(jié)果果然是0:
需要額外說明的是矿卑,由于monitor、trace沃饶、watch等命令是通過字節(jié)碼增強(qiáng)技術(shù)來實現(xiàn)的母廷,會在指定類的方法中插入一些切面來實現(xiàn)數(shù)據(jù)統(tǒng)計和觀測轻黑,因此診斷結(jié)束要執(zhí)行shutdown來還原類或方法字節(jié)碼,然后退出Arthas琴昆。
在這個案例中氓鄙,我們通過Arthas工具排查了高CPU的問題:
- 首先,通過dashboard?+?thread命令业舍,基本可以在幾秒鐘內(nèi)一鍵定位問題抖拦,找出消耗CPU最多的線程和方法棧;
- 然后舷暮,直接jad反編譯相關(guān)代碼态罪,來確認(rèn)根因;
- 此外下面,如果調(diào)用入?yún)⒉幻鞔_的話复颈,可以使用watch觀察方法入?yún)ⅲ⒏鶕?jù)方法執(zhí)行時間來過濾慢請求的入?yún)ⅰ?/li>
可?沥割,使用Arthas來定位生產(chǎn)問題根本用不著原始代碼券膀,也用不著通過增加日志來幫助我們分析入?yún)ⅲ粋€工具即可完成定位問題驯遇、分析問題的全套流程。