arthas 的一些高级调试技巧

梦康 2021-12-02 22:07:10 712

直接使用 arthas debug 我们常用的命令有 watch、trace 和 stack,但是很多时候干扰信息太多了,终端日志滚动太快,怎么办呢?条件表达式就能帮忙啦。下面是两个非常典型的使用场景,大家一起看下。

查看指定条件的出参入参

比如我们org.jsoup.nodes.Element.select调用的地方特别多,想监控某个具体的执行,就需要指定参数时才打印,那么就可以用watch 条件表达式。官方给的文档是

watch -v -x 2 demo.MathGame print 'params' 'params[0] > 100000'

依葫芦画瓢我试了下字符串的比较,ok,记录下

watch org.jsoup.nodes.Element select '{params,returnObj,throwExp}' -v -n 5 -x 3 "params[0] == '.user-center-top-left img'"
[arthas@12050]$ watch org.jsoup.nodes.Element select '{params,returnObj,throwExp}' -v -n 5 -x 3 "params[0] == '.user-center-top-left img'"
Press Q or Ctrl+C to abort.
Affect(class count: 2 , method count: 1) cost in 466 ms, listenerId: 1
Condition express: params[0] == '.user-center-top-left img' , result: false
Condition express: params[0] == '.user-center-top-left img' , result: false
Condition express: params[0] == '.user-center-top-left img' , result: false
Condition express: params[0] == '.user-center-top-left img' , result: false
Condition express: params[0] == '.user-center-top-left img' , result: true
Condition express: params[0] == '.user-center-top-left img' , result: false
Condition express: params[0] == '.user-center-top-left img' , result: false
Condition express: params[0] == '.user-center-top-left img' , result: true
method=org.jsoup.nodes.Element.select location=AtExitmethod=org.jsoup.nodes.Element.select location=AtExit

ts=2021-11-08 14:56:04; [cost=0.305363ms] result=@ArrayList[
    @Object[][
        @String[.user-center-top-left img],
    ],
    @Elements[
        @Element[
            EMPTY_NODES=@EmptyList[isEmpty=true;size=0],
            classSplit=@Pattern[\s+],
            tag=@Tag[img],
            shadowChildrenRef=null,
            childNodes=@EmptyList[isEmpty=true;size=0],
            attributes=@Attributes[ class="user-img" src="https://img.alicdn.com/imgextra/i1/O1CN01VausKw1cJgcewyHr6_!!6000000003580-2-tps-108-108.png" alt=""],
            baseUri=@String[],
            EmptyString=@String[],
            parentNode=@Element[<div class="user-center-top-left">
 <img class="user-img" src="https://img.alicdn.com/imgextra/i1/O1CN01VausKw1cJgcewyHr6_!!6000000003580-2-tps-108-108.png" alt="">
</div>],
            siblingIndex=@Integer[1],
        ],
    ],
    null,
]

如果想快速验证订正后的代码逻辑,比如这里 select 逻辑变动,可以直接利用 target 属性操作

watch org.jsoup.nodes.Element select "{params,target.select('.user-center-top-left.user-img-link img'),returnObj,throwExp}" -v -n 5 -x 3 "params[0] == '.user-center-top-left img'"

查看指定条件下的调用栈

比如有一个方法的参数,自己从逻辑上推论是不可能存在 size() 为 0 的情况,但是实际是有调用量的,为了排除其他干扰,可以这样,就能看到非预期的调用链路了

stack xxxxService batchGetBizContent -v  'params[0].size() == 0'
Condition express: params[0].size() == 0 , result: false
Condition express: params[0].size() == 0 , result: false
Condition express: params[0].size() == 0 , result: true
ts=2021-12-01 19:09:24;thread_name=AsyncRpcUtils-pool-12;id=166;is_daemon=false;priority=5;TCCL=org.springframework.boot.context.embedded.tomcat.TomcatEmbeddedWebappClassLoader@5a1bc790;trace_id=0be3e0a716383569641678960e44cc;rpc_id=0.1.1
    @com.sun.proxy.$Proxy271.batchGetBizContent()
        at xxxService.getRelatedArticleList(DeveloperRightComponentV2Service.java:315)
        at xxxController.lambda$detail$69(DeveloperArticleController.java:288)
        at xxx.CompletableFutureWrapper.lambda$supplyAsync$7(CompletableFutureWrapper.java:41)
        at java.util.concurrent.CompletableFuture$AsyncSupply.run(CompletableFuture.java:1590)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1152)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:627)
        at java.lang.Thread.run(Thread.java:882)