编程的魅力
首页
分类
标签
归档
动态
关于我
hyuga
2020-05-27
136
2020-07-28 11:07:58
原创
阿里巴巴-Arthas诊断工具
# 官方简介 `Arthas`(阿尔萨斯)是阿里巴巴开源的 Java 诊断工具 官方文档:[https://alibaba.github.io/arthas](https://alibaba.github.io/arthas) 项目地址:[https://gitee.com/arthas/arthas](https://gitee.com/arthas/arthas) # Arthas  `Arthas` 是Alibaba开源的Java诊断工具,深受开发者喜爱。 当你遇到以下类似问题而束手无策时,Arthas可以帮助你解决: - 这个类从哪个 jar 包加载的?为什么会报各种类相关的 Exception? - 我改的代码为什么没有执行到?难道是我没 commit?分支搞错了? - 遇到问题无法在线上 debug,难道只能通过加日志再重新发布吗? - 线上遇到某个用户的数据处理有问题,但线上同样无法 debug,线下无法重现! - 是否有一个全局视角来查看系统的运行状况? - 有什么办法可以监控到JVM的实时运行状态? `Arthas`支持JDK 6+,支持Linux/Mac/Windows,采用命令行交互模式,同时提供丰富的 Tab 自动补全功能,进一步方便进行问题的定位和诊断。 ## 在线教程(推荐) - [基础教程](https://alibaba.github.io/arthas/arthas-tutorials?language=cn&id=arthas-basics) - [进阶教程](https://alibaba.github.io/arthas/arthas-tutorials?language=cn&id=arthas-advanced) - [详细教程](https://alibaba.github.io/arthas/install-detail.html) ## 三种安装方式 > 第一种 按官方推荐的快速开始方法!使用`arthas-boot.jar`,用jar包方式启动。 ``` wget https://alibaba.github.io/arthas/arthas-boot.jar java -jar arthas-boot.jar ``` 这里遇到一点小问题,linux上没有安装wget,这个自行百度下,或者参考 [Linux 常规指令技巧](http://github.hyuga.top/2019/05/16/linux-command/) 如果下载速度比较慢,可以使用aliyun的镜像:`java -jar arthas-boot.jar --repo-mirror aliyun --use-http` > 第二种 打开项目地址,找到最新的一个标签,拉取最新的一个可用包下载。 下载后解压可得arthas目录,里面有可运行文件 `/arthas/bin/as.sh` https://gitee.com/arthas/arthas/repository/archive/arthas-all-3.1.1 > 第三种 这种也是相对最方便的一种:`curl -L https://alibaba.github.io/arthas/install.sh | sh` 官方是这样介绍的:Arthas 支持在 Linux/Unix/Mac 等平台上一键安装,请复制以下内容,并粘贴到命令行中,敲 回车 执行即可。 上述命令会下载启动脚本文件 as.sh 到当前目录,你可以放在任何地方或将其加入到 $PATH 中。 直接在shell下面执行./as.sh,就会进入交互界面。 也可以执行./as.sh -h来获取更多参数信息。 ## 指定端口启动 端口冲突时,通过以下命令启动: `java -jar /data/www/hyuga/arthas-boot.jar --telnet-port 9998 --http-port -1` ## Exit/Shutdown 退出Arthas 用 `exit` 或者 `quit` 命令可以退出`Arthas`。 ## 重连Arthas 退出`Arthas`之后,还可以再次用 `java -jar arthas-boot.jar` 来连接。 ## 彻底退出`Arthas` `exit/quit`命令只是退出当前`session`,`arthas server`还在目标进程中运行。 想完全退出`Arthas`,可以执行 `shutdown` 命令。 # 使用 ## Dashboard 系统实时数据面板  输入`Q` + `回车` 或者 `Ctrl + C` 可以退出`dashboard`命令。 ## sysprop `sysprop` 可以打印所有的System Properties信息。 `sysprop java.version` 也可以指定单个key `sysprop | grep user` 也可以通过grep来过滤 `sysprop testKey testValue` 可以设置新的value[慎用] ## sysenv `sysenv` 命令可以获取到环境变量。和sysprop命令类似。相对sysprop信息简化不少。 ## jvm `jvm` 命令会打印出JVM的各种详细信息。 ## help Arthas里每一个命令都有详细的帮助信息。可以用-h来查看。帮助信息里有EXAMPLES和WIKI链接。 eg: `sysprop -h` ## 自动补全 Arthas支持丰富的自动补全功能,在使用有疑惑时,可以输入`Tab`来获取更多信息。 ## readline的快捷键支持 Arthas支持常见的命令行快捷键,比如Ctrl + A跳转行首,Ctrl + E跳转行尾。 更多的快捷键可以用执行`keymap`命令查看。 ## 历史命令的补全 如果想再执行之前的命令,可以在输入一半时,按`Up/↑` 或者 `Ddown/↓`,来匹配到之前的命令。 比如之前执行过sysprop java.version,那么在输入sysprop ja之后,可以输入`Up/↑`,就会自动补全为sysprop java.version。 如果想查看所有的历史命令,也可以通过`history`命令查看到。 ## pipeline Arthas支持在`pipeline`(管道)之后,执行一些简单的命令,比如: `sysprop | grep java` `sysprop | wc -l` ## Sc 命令 可以通过 sc 命令来查找JVM里已加载的类! 如果搜索的是接口,还会搜索所有的实现类。比如查看所有的Filter实现类: `sc javax.servlet.Filter` 通过-d参数,可以打印出类加载的具体信息,很方便查找类加载问题。 `sc -d javax.servlet.Filter` sc支持通配,比如搜索所有的MathGame: `sc -d *MathGame` 根据包名+类名查看某个已被JVM加载的类,也可以通过星号进行模糊查询。 > sc查找加载UserController的ClassLoader `sc -d *UserController | grep classLoaderHash` ``` $ sc -d *UserController | grep classLoaderHash classLoaderHash 1be6f5c3 ``` 可以发现是 spring boot LaunchedURLClassLoader@1be6f5c3 加载的。 ## mc 使用mc(Memory Compiler)命令可以编译java文件,并且通过-c参数指定ClassLoader: `mc -c 1be6f5c3 /tmp/UserController.java -d /tmp` **1be6f5c3**是通过`sc`命令查找出来的加载UserController.java类的类加载器的hashCode ``` $ mc -c 1be6f5c3 /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`命令指定类加载器重新编译java类,编译好的class文件存储在包名同路径下 ## redefine 使用redefine命令重新加载新编译好的UserController.class: `redefine /tmp/com/example/demo/arthas/user/UserController.class` ``` $ redefine /tmp/com/example/demo/arthas/user/UserController.class redefine success, size: 1 ``` 通过jad反编译保存源码,修改源码,sc查找对应类加载器,mc指定类加载器重新编译java文件,redefine重新加载编译好的class文件 ## Sm 命令 `sm`命令则是查找类的具体函数。比如: `sm java.math.RoundingMode` 通过-d参数可以打印函数的具体属性: `sm -d java.math.RoundingMode` 也可以查找特定的函数,比如查找构造函数: `sm java.math.RoundingMode
` > demo `sm -d com.syzl.web.mgr.controller.security.system.CityCompanySettingController pageCityCompany` 非常直观的打印出`pageCityCompany`方法的各种详细信息,做线上排查非常有帮助。 ## thread 查看线程 `thread` 打印所有应用所有线程信息 `thread 16` 查看线程ID 16的栈 `thread -n 3` 查看CPU使用率top n线程的栈 `thread -n 3 -i 5000` 查看5秒内的CPU使用率top n线程栈 `thread -b` 查找线程是否有阻塞 ## 获取 Main Class `thread 1 | grep 'main('` ``` $ thread 1 | grep 'main(' at demo.MathGame.main(MathGame.java:17) ``` ## Jad 反编译 非常实用的一个功能!!!可以通过 jad 命令来反编译代码: `jad com.example.demo.arthas.user.UserController` 通过--source-only参数可以只打印出在反编译的源代码: `jad --source-only com.example.demo.arthas.user.UserController` 反编译内容保存到文件: `jad --source-only com.example.demo.arthas.user.UserController > /tmp/UserController.java` jad反编译的结果保存在 /tmp/UserController.java文件里了。 很强的功能,直接根据包名+类名,反编译出线上某个已被jvm加载的类的源码信息。 ## Watch 命令 通过watch命令可以查看函数的参数/返回值/异常信息。 `watch com.example.demo.arthas.user.UserController * '{params, returnObj, throwExp}'` - 第一个参数是类名,支持通配 - 第二个参数是函数名,支持通配 - 第三个参数是返回值表达式,它实际上是一个ognl表达式,它支持一些内置对象: - loader clazz method target params returnObj throwExp isBefore isThrow isReturn 如果想把获取到的结果展开,可以用-x参数: `watch com.example.demo.arthas.user.UserController * '{params, returnObj, throwExp}' -x 2` 更多参考: https://alibaba.github.io/arthas/advice-class.html 输入 `Q` 或者 `Ctrl+C` 退出watch命令。 > demo `watch com.syzl.web.mgr.controller.security.system.CityCompanySettingController pageCityCompany returnObj` 很强大的功能,根据包名+类名+方法名,可以打印出接口实时调用所返回的数据,并且打印出该接口调用时间和调用响应总时长。 > 条件表达式 watch命令支持在第4个参数里写条件表达式,比如: `watch com.example.demo.arthas.user.UserController * returnObj 'params[0] > 100'` 当访问 `https://2886795319-80-elsy02.environments.katacoda.com/user/1` 时,watch命令没有输出 当访问 `https://2886795319-80-elsy02.environments.katacoda.com/user/101` 时,watch会打印出结果。 > 当异常时捕获 watch命令支持-e选项,表示只捕获抛出异常时的请求: `watch com.example.demo.arthas.user.UserController * "{params[0],throwExp}" -e` or `watch com.example.demo.arthas.user.UserController * "{params[0],throwExp}" -e -x 2` 打印具体异常信息 > 按照耗时进行过滤 watch命令支持按请求耗时进行过滤,比如: `watch com.example.demo.arthas.user.UserController * '{params, returnObj}' '#cost>200'` ## trace > 跟踪所有的Filter函数 `trace javax.servlet.Filter *` > 跟踪所有的Servlet函数 `trace javax.servlet.Servlet * > /tmp/servlet.txt` ## classloader > 列出所有ClassLoader `classloader -l` > 查看ClassLoader树 `classloader -t` > 列出ClassLoader里加载的所有类 `classloader -a -c 65361d9a(类加载器hashCode)` > 列出ClassLoader的urls `classloader -c 1be6f5c3` > 加载指定ClassLoader里的资源文件 查找指定的资源文件: `classloader -c 1be6f5c3 -r logback-spring.xml` > 尝试加载指定的类 比如用上面的spring LaunchedURLClassLoader 尝试加载 java.lang.String : `classloader -c 1be6f5c3 --load java.lang.String` # 进阶命令 ## 基础命令 - help——查看命令帮助信息 - [cat](https://alibaba.github.io/arthas/cat.html)——打印文件内容,和linux里的cat命令类似 - [pwd](https://alibaba.github.io/arthas/pwd.html)——返回当前的工作目录,和linux命令类似 - cls——清空当前屏幕区域 - session——查看当前会话的信息 - [reset](https://alibaba.github.io/arthas/reset.html)——重置增强类,将被 Arthas 增强过的类全部还原,Arthas 服务端关闭时会重置所有增强过的类 - Arthas在 watch/trace 等命令时,实际上是修改了应用的字节码,插入增强的代码。显式执行 reset 命令,可以清除掉这些增强代码。 - version——输出当前目标 Java 进程所加载的 Arthas 版本号 - history——打印命令历史 - quit——退出当前 Arthas 客户端,其他 Arthas 客户端不受影响 - shutdown——关闭 Arthas 服务端,所有 Arthas 客户端全部退出 - [keymap](https://alibaba.github.io/arthas/keymap.html)——Arthas快捷键列表及自定义快捷键 ## JVM相关 - [dashboard](https://alibaba.github.io/arthas/dashboard.html)——当前系统的实时数据面板 - [thread](https://alibaba.github.io/arthas/thread.html)——查看当前 JVM 的线程堆栈信息 - [jvm](https://alibaba.github.io/arthas/jvm.html)——查看当前 JVM 的信息 - [sysprop](https://alibaba.github.io/arthas/sysprop.html)——查看和修改JVM的系统属性 - [sysenv](https://alibaba.github.io/arthas/sysenv.html)——查看JVM的环境变量 - [getstatic](https://alibaba.github.io/arthas/getstatic.html)——查看类的静态属性 - New! [ognl](https://alibaba.github.io/arthas/ognl.html)——执行ognl表达式 - New! [mbean](https://alibaba.github.io/arthas/mbean.html)——查看 Mbean 的信息 ## class/classloader相关 - [sc](https://alibaba.github.io/arthas/sc.html)——查看JVM已加载的类信息 - [sm](https://alibaba.github.io/arthas/sm.html)——查看已加载类的方法信息 - [jad](https://alibaba.github.io/arthas/jad.html)——反编译指定已加载类的源码 - [mc](https://alibaba.github.io/arthas/mc.html)——内存编绎器,内存编绎.java文件为.class文件 - [redefine](https://alibaba.github.io/arthas/redefine.html)——加载外部的.class文件,redefine到JVM里 - [dump](https://alibaba.github.io/arthas/dump.html)——dump 已加载类的 byte code 到特定目录 - [classloader](https://alibaba.github.io/arthas/classloader.html)——查看classloader的继承树,urls,类加载信息,使用classloader去getResource ## monitor/watch/trace相关 **请注意,这些命令,都通过字节码增强技术来实现的,会在指定类的方法中插入一些切面来实现数据统计和观测,因此在线上、预发使用时,请尽量明确需要观测的类、方法以及条件,诊断结束要执行 `shutdown` 或将增强过的类执行 `reset` 命令。** - [monitor](https://alibaba.github.io/arthas/monitor.html)——方法执行监控 - [watch](https://alibaba.github.io/arthas/watch.html)——方法执行数据观测 - [trace](https://alibaba.github.io/arthas/trace.html)——方法内部调用路径,并输出方法路径上的每个节点上耗时 - [stack](https://alibaba.github.io/arthas/stack.html)——输出当前方法被调用的调用路径 - [tt](https://alibaba.github.io/arthas/tt.html)——方法执行数据的时空隧道,记录下指定方法每次调用的入参和返回信息,并能对这些不同的时间下调用进行观测 ## options - [options](https://alibaba.github.io/arthas/options.html)——查看或设置Arthas全局开关 ## 管道 Arthas支持使用管道对上述命令的结果进行进一步的处理,如`sm java.lang.String * | grep 'index'` - grep——搜索满足条件的结果 - plaintext——将命令的结果去除ANSI颜色 - wc——按行统计输出结果 ## 后台异步任务 当线上出现偶发的问题,比如需要watch某个条件,而这个条件一天可能才会出现一次时,异步后台任务就派上用场了,详情请参考[这里](https://alibaba.github.io/arthas/async.html) 使用 `>` 将结果重写向到日志文件,使用 `&` 指定命令是后台运行,`session`断开不影响任务执行(生命周期默认为1天) - jobs——列出所有job - kill——强制终止任务 - fg——将暂停的任务拉到前台执行 - bg——将暂停的任务放到后台执行 ## Web Console 通过websocket连接Arthas。 - [Web Console](https://alibaba.github.io/arthas/web-console.html)
Arthas
评论
发布
留言
评论