环境准备: #下载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 命令,可以清除掉这些增强代码
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)