欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

arthas

程序员文章站 2022-07-15 15:42:29
...

案例: 排查函数调用异常(watch)

Arthas在 watch/trace 等命令时,实际上是修改了应用的字节码,插入增强的代码。显式执行 reset 命令,可以清除掉这些增强代码。
现象
访问 http://localhost:61000/user/0 ,会返回500异常:
在Arthas里执行(进行监控)

watch com.example.demo.arthas.user.UserController * '{params, throwExp}' -x 2

当发送请求时,就会打印日志信息;可以查看到具体的报错信息
返回值表达式
在上面的例子里,第三个参数是返回值表达式,它实际上是一个ognl表达式,它支持一些内置对象:
loader
clazz
method
target
params
returnObj
throwExp
isBefore
isThrow
isReturn
watch命令参考文档
watch命令支持在第4个参数里写条件表达式,比如:

watch com.example.demo.arthas.user.UserController * returnObj 'params[0] > 100'

当访问 user/1 时,watch命令没有输出

当访问 user/101 时,watch会打印出结果。

watch命令支持按抛出异常进行过滤

watch com.example.demo.arthas.user.UserController * "{params[0],throwExp}" -e

watch命令支持按请求耗时进行过滤,比如:

watch com.example.demo.arthas.user.UserController * '{params, returnObj}' '#cost>200'

案例: 热更新代码(jad/mc/redefine)

  1. jad命令反编译UserController
 jad --source-only com.example.demo.arthas.user.UserController > /tmp/UserController.java
  1. 修改代码
  2. sc命令查找加载具体类(UserController)的具体ClassLoader,使用此类加载器重新编译加载代码
 sc -d *UserController | grep classLoaderHash
 classLoaderHash   1be6f5c3

请记下你的classLoaderHash,后面需要使用它。在这里,它是 1be6f5c3。

  1. 使用mc(Memory Compiler)命令来编译,并且通过-c或者–classLoaderClass参数指定ClassLoader
mc --classLoaderClass org.springframework.boot.loader.LaunchedURLClassLoader /tmp/UserController.java -d /tmp
Memory compiler output:
/tmp/com/example/demo/arthas/user/UserController.class
Affect(row-cnt:1) cost in 346 ms

也可以通过mc -c /tmp/UserController.java -d /tmp,使用-c参数指定ClassLoaderHash:

mc -c 1be6f5c3 /tmp/UserController.java -d /tmp
  1. 再使用redefine命令重新加载新编译好的UserController.class:
$ redefine /tmp/com/example/demo/arthas/user/UserController.class
redefine success, size: 1

动态更新应用Logger Level

查找UserController的ClassLoader

sc -d com.example.demo.arthas.user.UserController | grep classLoaderHash
 classLoaderHash   1be6f5c3

用ognl获取logger

ognl --classLoaderClass org.springframework.boot.loader.LaunchedURLClassLoader '@[email protected]'

可以知道[email protected]实际使用的是logback。可以看到level=null,则说明实际最终的level是从root logger里来的。

单独设置UserController的logger level

ognl --classLoaderClass org.springframework.boot.loader.LaunchedURLClassLoader '@[email protected](@[email protected])'

再次获取[email protected],可以发现已经是DEBUG了:

ognl --classLoaderClass org.springframework.boot.loader.LaunchedURLClassLoader '@[email protected]'

修改logback的全局logger level
通过获取root logger,可以修改全局的logger level:

ognl --classLoaderClass org.springframework.boot.loader.LaunchedURLClassLoader '@[email protected]("root").setLevel(@[email protected])'

案例: 排查logger冲突问题

案例: 获取Spring Context

tt -t 类 方法

tt -t org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter invokeHandlerMethod

使用tt命令从调用记录里获取到spring context

tt -i 1000 -w 'target.getApplicationContext()'

获取spring bean,并调用函数

案例: 排查HTTP请求返回401

trace javax.servlet.Filter *
stack javax.servlet.http.HttpServletResponse sendError 'params[0]==401'

案例: 排查HTTP请求返回404

trace javax.servlet.Servlet * > /tmp/servlet.txt

案例: 理解Spring Boot应用的ClassLoader结构

classloader -l

案例:查找Top N线程

查看5秒内的CPU使用率top n线程栈

thread -n 3 -i 5000
相关标签: java jvm