--- title: Arthas 快速入门 date: 2020-02-07 23:04:47 order: 05 categories: - Java - 软件 - 监控诊断 tags: - Java - 诊断 - Arthas permalink: /pages/1d699188/ --- # Arthas 快速入门 > `Arthas` 是 Alibaba 开源的 Java 诊断工具 。 ## 简介 `Arthas`可以解决的问题: 1. 这个类从哪个 jar 包加载的?为什么会报各种类相关的 Exception? 2. 我改的代码为什么没有执行到?难道是我没 commit?分支搞错了? 3. 遇到问题无法在线上 debug,难道只能通过加日志再重新发布吗? 4. 线上遇到某个用户的数据处理有问题,但线上同样无法 debug,线下无法重现! 5. 是否有一个全局视角来查看系统的运行状况? 6. 有什么办法可以监控到 JVM 的实时运行状态? `Arthas`支持 JDK 6+,支持 Linux/Mac/Windows,采用命令行交互模式,同时提供丰富的 `Tab` 自动补全功能,进一步方便进行问题的定位和诊断。 ## 安装 ### 使用`arthas-boot`(推荐) 下载`arthas-boot.jar`,然后用`java -jar`的方式启动: ``` wget https://alibaba.github.io/arthas/arthas-boot.jar java -jar arthas-boot.jar ``` 打印帮助信息: ``` java -jar arthas-boot.jar -h ``` - 如果下载速度比较慢,可以使用 aliyun 的镜像: ``` java -jar arthas-boot.jar --repo-mirror aliyun --use-http ``` - 如果从 github 下载有问题,可以使用 gitee 镜像 ``` wget https://arthas.gitee.io/arthas-boot.jar ``` ### 使用`as.sh` Arthas 支持在 Linux/Unix/Mac 等平台上一键安装,请复制以下内容,并粘贴到命令行中,敲 `回车` 执行即可: ``` curl -L https://alibaba.github.io/arthas/install.sh | sh ``` 上述命令会下载启动脚本文件 `as.sh` 到当前目录,你可以放在任何地方或将其加入到 `$PATH` 中。 直接在 shell 下面执行`./as.sh`,就会进入交互界面。 也可以执行`./as.sh -h`来获取更多参数信息。 - 如果从 github 下载有问题,可以使用 gitee 镜像 ``` curl -L https://arthas.gitee.io/install.sh | sh ``` ### 全量安装 最新版本,点击下载:[下载地址](http://repository.sonatype.org/service/local/artifact/maven/redirect?r=central-proxy&g=com.taobao.arthas&a=arthas-packaging&e=zip&c=bin&v=LATEST) 解压后,在文件夹里有`arthas-boot.jar`,直接用`java -jar`的方式启动: ``` java -jar arthas-boot.jar ``` 打印帮助信息: ``` java -jar arthas-boot.jar -h ``` ## 基础使用 ### 启动 Demo ```bash wget https://alibaba.github.io/arthas/arthas-demo.jar java -jar arthas-demo.jar ``` `arthas-demo`是一个简单的程序,每隔一秒生成一个随机数,再执行质因式分解,并打印出分解结果。 `arthas-demo`源代码:[查看](https://github.com/alibaba/arthas/blob/master/demo/src/main/java/demo/MathGame.java) ### 启动 arthas 在命令行下面执行(使用和目标进程一致的用户启动,否则可能 attach 失败): ``` wget https://alibaba.github.io/arthas/arthas-boot.jar java -jar arthas-boot.jar ``` - 执行该程序的用户需要和目标进程具有相同的权限。比如以`admin`用户来执行:`sudo su admin && java -jar arthas-boot.jar` 或 `sudo -u admin -EH java -jar arthas-boot.jar`。 - 如果 attach 不上目标进程,可以查看`~/logs/arthas/` 目录下的日志。 - 如果下载速度比较慢,可以使用 aliyun 的镜像:`java -jar arthas-boot.jar --repo-mirror aliyun --use-http` - `java -jar arthas-boot.jar -h` 打印更多参数信息。 选择应用 java 进程: ```bash $ $ java -jar arthas-boot.jar * [1]: 35542 [2]: 71560 arthas-demo.jar ``` Demo 进程是第 2 个,则输入 2,再输入`回车/enter`。Arthas 会 attach 到目标进程上,并输出日志: ```bash [INFO] Try to attach process 71560 [INFO] Attach process 71560 success. [INFO] arthas-client connect 127.0.0.1 3658 ,---. ,------. ,--------.,--. ,--. ,---. ,---. / O \ | .--. ''--. .--'| '--' | / O \ ' .-' | .-. || '--'.' | | | .--. || .-. |`. `-. | | | || |\ \ | | | | | || | | |.-' | `--' `--'`--' '--' `--' `--' `--'`--' `--'`-----' wiki: https://alibaba.github.io/arthas version: 3.0.5.20181127201536 pid: 71560 time: 2018-11-28 19:16:24 $ ``` ### 查看 dashboard 输入[dashboard](https://alibaba.github.io/arthas/dashboard.html),按`回车/enter`,会展示当前进程的信息,按`ctrl+c`可以中断执行。 ```bash $ dashboard ID NAME GROUP PRIORI STATE %CPU TIME INTERRU DAEMON 17 pool-2-thread-1 system 5 WAITIN 67 0:0 false false 27 Timer-for-arthas-dashb system 10 RUNNAB 32 0:0 false true 11 AsyncAppender-Worker-a system 9 WAITIN 0 0:0 false true 9 Attach Listener system 9 RUNNAB 0 0:0 false true 3 Finalizer system 8 WAITIN 0 0:0 false true 2 Reference Handler system 10 WAITIN 0 0:0 false true 4 Signal Dispatcher system 9 RUNNAB 0 0:0 false true 26 as-command-execute-dae system 10 TIMED_ 0 0:0 false true 13 job-timeout system 9 TIMED_ 0 0:0 false true 1 main main 5 TIMED_ 0 0:0 false false 14 nioEventLoopGroup-2-1 system 10 RUNNAB 0 0:0 false false 18 nioEventLoopGroup-2-2 system 10 RUNNAB 0 0:0 false false 23 nioEventLoopGroup-2-3 system 10 RUNNAB 0 0:0 false false 15 nioEventLoopGroup-3-1 system 10 RUNNAB 0 0:0 false false Memory used total max usage GC heap 32M 155M 1820M 1.77% gc.ps_scavenge.count 4 ps_eden_space 14M 65M 672M 2.21% gc.ps_scavenge.time(m 166 ps_survivor_space 4M 5M 5M s) ps_old_gen 12M 85M 1365M 0.91% gc.ps_marksweep.count 0 nonheap 20M 23M -1 gc.ps_marksweep.time( 0 code_cache 3M 5M 240M 1.32% ms) Runtime os.name Mac OS X os.version 10.13.4 java.version 1.8.0_162 java.home /Library/Java/JavaVir tualMachines/jdk1.8.0 _162.jdk/Contents/Hom e/jre ``` ### 通过 thread 命令来获取到`arthas-demo`进程的 Main Class `thread 1`会打印线程 ID 1 的栈,通常是 main 函数的线程。 ```bash $ thread 1 | grep 'main(' at demo.MathGame.main(MathGame.java:17) ``` ### 通过 jad 来反编译 Main Class ```java $ jad demo.MathGame ClassLoader: +-sun.misc.Launcher$AppClassLoader@3d4eac69 +-sun.misc.Launcher$ExtClassLoader@66350f69 Location: /tmp/arthas-demo.jar /* * Decompiled with CFR 0_132. */ package demo; import java.io.PrintStream; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import java.util.Random; import java.util.concurrent.TimeUnit; public class MathGame { private static Random random = new Random(); private int illegalArgumentCount = 0; public static void main(String[] args) throws InterruptedException { MathGame game = new MathGame(); do { game.run(); TimeUnit.SECONDS.sleep(1L); } while (true); } public void run() throws InterruptedException { try { int number = random.nextInt(); List primeFactors = this.primeFactors(number); MathGame.print(number, primeFactors); } catch (Exception e) { System.out.println(String.format("illegalArgumentCount:%3d, ", this.illegalArgumentCount) + e.getMessage()); } } public static void print(int number, List primeFactors) { StringBuffer sb = new StringBuffer("" + number + "="); Iterator iterator = primeFactors.iterator(); while (iterator.hasNext()) { int factor = iterator.next(); sb.append(factor).append('*'); } if (sb.charAt(sb.length() - 1) == '*') { sb.deleteCharAt(sb.length() - 1); } System.out.println(sb); } public List primeFactors(int number) { if (number < 2) { ++this.illegalArgumentCount; throw new IllegalArgumentException("number is: " + number + ", need >= 2"); } ArrayList result = new ArrayList(); int i = 2; while (i <= number) { if (number % i == 0) { result.add(i); number /= i; i = 2; continue; } ++i; } return result; } } Affect(row-cnt:1) cost in 970 ms. ``` ### watch 通过[watch](https://alibaba.github.io/arthas/watch.html)命令来查看`demo.MathGame#primeFactors`函数的返回值: ```bash $ watch demo.MathGame primeFactors returnObj Press Ctrl+C to abort. Affect(class-cnt:1 , method-cnt:1) cost in 107 ms. ts=2018-11-28 19:22:30; [cost=1.715367ms] result=null ts=2018-11-28 19:22:31; [cost=0.185203ms] result=null ts=2018-11-28 19:22:32; [cost=19.012416ms] result=@ArrayList[ @Integer[5], @Integer[47], @Integer[2675531], ] ts=2018-11-28 19:22:33; [cost=0.311395ms] result=@ArrayList[ @Integer[2], @Integer[5], @Integer[317], @Integer[503], @Integer[887], ] ts=2018-11-28 19:22:34; [cost=10.136007ms] result=@ArrayList[ @Integer[2], @Integer[2], @Integer[3], @Integer[3], @Integer[31], @Integer[717593], ] ts=2018-11-28 19:22:35; [cost=29.969732ms] result=@ArrayList[ @Integer[5], @Integer[29], @Integer[7651739], ] ``` 更多的功能可以查看[进阶使用](https://alibaba.github.io/arthas/advanced-use.html)。 ### 退出 arthas 如果只是退出当前的连接,可以用`quit`或者`exit`命令。Attach 到目标进程上的 arthas 还会继续运行,端口会保持开放,下次连接时可以直接连接上。 如果想完全退出 arthas,可以执行`shutdown`命令。 ## 进阶使用 ### 基础命令 - 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 服务端关闭时会重置所有增强过的类 - 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 的环境变量 - [vmoption](https://alibaba.github.io/arthas/vmoption.html)——查看和修改 JVM 里诊断相关的 option - [logger](https://alibaba.github.io/arthas/logger.html)——查看和修改 logger - [getstatic](https://alibaba.github.io/arthas/getstatic.html)——查看类的静态属性 - [ognl](https://alibaba.github.io/arthas/ognl.html)——执行 ognl 表达式 - [mbean](https://alibaba.github.io/arthas/mbean.html)——查看 Mbean 的信息 - [heapdump](https://alibaba.github.io/arthas/heapdump.html)——dump java heap, 类似 jmap 命令的 heap dump 功能 ### 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) ### 用户数据回报 在`3.1.4`版本后,增加了用户数据回报功能,方便统一做安全或者历史数据统计。 在启动时,指定`stat-url`,就会回报执行的每一行命令,比如: `./as.sh --stat-url 'http://192.168.10.11:8080/api/stat'` 在 tunnel server 里有一个示例的回报代码,用户可以自己在服务器上实现。 [StatController.java](https://github.com/alibaba/arthas/blob/master/tunnel-server/src/main/java/com/alibaba/arthas/tunnel/server/app/web/StatController.java) ### 其他特性 - [异步命令支持](https://alibaba.github.io/arthas/async.html) - [执行结果存日志](https://alibaba.github.io/arthas/save-log.html) - [批处理的支持](https://alibaba.github.io/arthas/batch-support.html) - [ognl 表达式的用法说明](https://github.com/alibaba/arthas/issues/11) ## 参考资料 - [Arthas Github](https://github.com/alibaba/arthas) - [Arthas 用户文档](https://alibaba.github.io/arthas/index.html) - [arthas 源码分析](https://www.jianshu.com/p/4e34d0ab47d1)