Arthas——Java診斷工具

官方文檔:https://arthas.aliyun.com/doc/

watch 查看函數調用的參數內容和返回值

watch  com.alibaba.middleware.drds.manager.common.utils.AddressUtil getHostIp "{params,returnObj}" -x 2

watch com.alibaba.middleware.drds.worker.task.RegisterTask getHostInfoIfNeeded "{params,returnObj}" -x 2
    Press Q or Ctrl+C to abort.
    Affect(class-cnt:1 , method-cnt:1) cost in 56 ms.
    ts=2019-09-27 13:24:00; [cost=0.2698ms] result=@ArrayList[
        @Object[][isEmpty=true;size=0],
        @Boolean[true],
    ]
    ts=2019-09-27 13:24:02; [cost=0.030039ms] result=@ArrayList[
        @Object[][isEmpty=true;size=0],
        @Boolean[true],
    ]

可以看到處理請求的handler是 om.example.demo.arthas.user.UserController.findUserById:

$ watch org.springframework.web.servlet.DispatcherServlet getHandler returnObj
Press Q or Ctrl+C to abort.
Affect(class-cnt:1 , method-cnt:1) cost in 332 ms.
ts=2019-06-04 11:38:06; [cost=2.75218ms] result=@HandlerExecutionChain[
    logger=@SLF4JLocationAwareLog[org.apache.commons.logging.impl.SLF4JLocationAwareLog@665c08a],
    handler=@HandlerMethod[public com.example.demo.arthas.user.User com.example.demo.arthas.user.UserController.findUserById(java.lang.Integer)],
    interceptors=null,
    interceptorList=@ArrayList[isEmpty=false;size=2],
    interceptorIndex=@Integer[-1],
]
  • watch 命令定義了4個觀察事件點,即 -b 方法調用前,-e 方法異常後,-s 方法返回後,-f 方法結束後
  • 4個觀察事件點 -b、-e、-s 默認關閉,-f 默認打開,當指定觀察點被打開後,在相應事件點會對觀察表達式進行求值並輸出
  • 這裏要注意方法入參和方法出參的區別,有可能在中間被修改導致前後不一致,除了 -b 事件點 params 代表方法入參外,其餘事件都代表方法出參
  • 當使用 -b 時,由於觀察事件點是在方法調用前,此時返回值或異常均不存在

tt 觀察函數調用和回放

先通過tt觀察某個函數的調用,然後再用 tt -i 回放這個調用並查看返回值等

tt -t com.alibaba.middleware.drds.manager.common.utils.AddressUtil getHostIp
tt -t com.alibaba.middleware.drds.worker.task.RegisterTask getHostInfoIfNeeded
tt -i 1000
tt -i 1000 -p
tt -n 3 -t com.alibaba.middleware.drds.worker.task.RegisterTask getHostInfoIfNeeded
tt -n 3 -t com.alibaba.middleware.drds.manager.common.utils.AddressUtil getHostIp

 tt -i 1010 -p
     RE-INDEX      1010
     GMT-REPLAY    2019-09-27 12:59:05
     OBJECT        NULL
     CLASS         com.alibaba.middleware.drds.manager.common.utils.AddressUtil
     METHOD        getHostIp
     IS-RETURN     true
     IS-EXCEPTION  false
     COST(ms)      0.577817
     RETURN-OBJ    @String[10.0.118.18]

trace 耗時超過10ms的方法堆棧

查看調用耗時超過 10ms的函數堆棧

stack ch.qos.logback.core.AppenderBase doAppend
trace -j ch.qos.logback.core.AppenderBase doAppend '#cost > 10'

sm

列出class的方法

sm ch.qos.logback.core.AppenderBase -d

hread

thread -n 3
thread 16

jad 反編譯

jad org.slf4j.Logger
jad org.slf4j.Logger -c 61bbe9ba

jad com.taobao.tddl.common.IdGenerator
jad --source-only com.taobao.tddl.common.IdGenerator
jad --source-only com.taobao.tddl.common.IdGenerator > /tmp/IdGenerator.java

反編譯生成java代碼

mc 編譯生成新的class

將修改後的java代碼編譯成class(因爲依賴的關係可能失敗)

mc /tmp/IdGenerator.java -d /tmp

redefine 加載新的class

將修改後的class代碼熱加載

redefine /tmp/IdGenerator.class
redefine -c 1e80bfe8 /tmp/com/alibaba/middleware/drds/worker/task/RegisterTask.class

可以再次jad 反編譯確認class中是修改後的代碼:

jad --source-only com.alibaba.cobar.server.ServerConnection > /tmp/SC.java

有時候 redefine 看到成功,可是實際並不一定,最好再次 jad 確認一下。

線上環境快速修改代碼驗證三部曲:jad反編譯得到源代碼、修改後mc編譯成class、redefine替換新的class。

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