直接使用 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)