arthas学习笔记

arthas学习笔记,第1张

arthas学习笔记 基础命令
环境准备:
#下载springboot-demo.jar
wget https://code.aliyun.com/middleware-container/handsonLabExternedFiles/raw/master/demo-arthas-spring-boot.jar;java -jar demo-arthas-spring-boot.jar
#下载arthas
wget https://arthas.aliyun.com/arthas-boot.jar;java -jar arthas-boot.jar --target-ip 0.0.0.0

help 查看所有命令说明
dashboard 仪表盘信息,展示 jvm的thread, memory, gc, vm, tomcat 等信息

sc  -d *MathGame(类名) :搜索已经被JVM加载的类信息
sm -d *MathGame(类名) :展示搜索到类的所有的方法

jad demo.MathGame(类的全路径名) 反编译出源码

watch [类名,支持通配符*] 方法名[支持通配符*]  {params,returnObj,throwExp} -x  n (-x n表示展开层级)  
#第一个参数是类名,支持通配
#第二个参数是函数名,支持通配 
#第三个参数是返回值表达式,它实际上是一个ognl表达式,它支持一些内置对象:
 1. loader
 2. clazz
 3. method
 4. target
 5. params
 6. returnObj
 7. throwExp
 8. isBefore
 9. isThrow
 10. isReturn
#你可以利用这些内置对象来组成不同的表达式。比如返回一个数组:
watch com.example.demo.arthas.user.UserController * '{params[0], target, returnObj}'
#更多参考: https://arthas.aliyun.com/doc/advice-class.html
#如果想把获取到的结果展开,可以用-x参数
#例子:
watch com.example.demo.arthas.user.UserController * '{params, throwExp,throwExp}' -x 2
#watch命令支持在第4个参数里写条件表达式,比如:
watch com.example.demo.arthas.user.UserController * returnObj 'params[0] > 100'
#当参数小于100 时,watch命令没有输出
#当参数> 100 时,watch会打印出结果

#当异常时捕获
#watch命令支持-e选项,表示只捕获抛出异常时的请求:
watch com.example.demo.arthas.user.UserController * "{params[0],throwExp}" -e

#按照耗时进行过滤
#watch命令支持按请求耗时进行过滤,比如:
watch com.example.demo.arthas.user.UserController * '{params, returnObj}' '#cost>20'

thread  n:  (n是线程id)列出指定的线程的栈信息,不带n时会列出当前进程的所有线程信息
thread -n 3:查看CPU使用率top 3线程的栈
thread -b:检查是否存在阻塞线程

trace: 监控方法调用过程,耗时等信息
用例:trace com.example.demo.arthas.user.UserController findUserById
进阶命令

sysprop:系统参数信息
sysenv :环境参数
热代码修改

#案例: 热更新代码
#通过jad/mc/redefine 命令实现动态更新代码的功能。
#目前,访问 http://localhost:61000/user/0 ,会返回500异常:
curl http://localhost:61000/user/0
{"timestamp":1550223186170,"status":500,"error":"Internal Server Error","exception":"java.lang.IllegalArgumentException","message":"id < 1","path":"/user/0"}

#通过热更新代码,修改这个逻辑。
jad 反编译UserController
jad --source-only com.example.demo.arthas.user.UserController > /tmp/UserController.java

#jad反编译的结果保存在 /tmp/UserController.java文件里了。
#再打开一个Terminal 3,然后用vim来编辑/tmp/UserController.java:
vim /tmp/UserController.java
#比如当 user id 小于1时,也正常返回,不抛出异常:
    @GetMapping(value={"/user/{id}"})
    public User findUserById(@PathVariable Integer id) {
        logger.info("id: {}", (Object)id);
        if (id == null) {
           throw new IllegalArgumentException("id < 1");
        }
        return new User(id.intValue(), "name" + id);
    }

#sc查找加载UserController的ClassLoader
sc -d *UserController | grep classLoaderHash

#可以发现是 spring boot LaunchedURLClassLoader@1be6f5c3 加载的。
#请记下你的classLoaderHash,后面需要使用它。在这里,它是 1be6f5c3。

mc
#保存好/tmp/UserController.java之后,使用mc(Memory Compiler)命令来编译,并且通过-c或者--classLoaderClass参数指定ClassLoader:
mc --classLoaderClass org.springframework.boot.loader.LaunchedURLClassLoader /tmp/UserController.java -d /tmp

$ mc --classLoaderClass org.springframework.boot.loader.LaunchedURLClassLoader /tmp/UserController.java -d /tmp

#也可以通过mc -c  /tmp/UserController.java -d /tmp,使用-c参数指定ClassLoaderHash:
$ mc -c 1be6f5c3 /tmp/UserController.java -d /tmp
redefine
#再使用redefine命令重新加载新编译好的UserController.class:
redefine /tmp/com/example/demo/arthas/user/UserController.class
#热修改代码结果
#redefine成功之后,再次访问 user/0 ,结果是:
{
  "id": 0,
  "name": "name0"
}

reset
#Arthas在 watch/trace 等命令时,实际上是修改了应用的字节码,插入增强的代码。显式执行 reset 命令,可以清除掉这些增强代码

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/zaji/5597382.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-12-15
下一篇 2022-12-15

发表评论

登录后才能评论

评论列表(0条)

保存