简介
是一款java的诊断工具
当你遇到以下类似问题而束手无策时,Arthas可以帮助你解决:
- 这个类从哪个 jar 包加载的?为什么会报各种类相关的 Exception?
- 我改的代码为什么没有执行到?难道是我没 commit?分支搞错了?
- 遇到问题无法在线上 debug,难道只能通过加日志再重新发布吗?
- 线上遇到某个用户的数据处理有问题,但线上同样无法 debug,线下无法重现!
- 是否有一个全局视角来查看系统的运行状况?
- 有什么办法可以监控到JVM的实时运行状态?
- 怎么快速定位应用的热点,生成火焰图?
归纳总结:Arthas通过JVM的Attach机制,在不影响服务连续性的情况下,实时连接到目标进程,便于工程师在线排查问题
下载启动
arthas是以jar的形式存在的,推荐用两种方式下载
- 全量下载:https://arthas.aliyun.com/download/latest_version?mirror=aliyun,解压即可
- 下载arthas-boot.jar,然后用java -jar的方式启动
curl -O https://arthas.aliyun.com/arthas-boot.jar java -jar arthas-boot.jar(或者使用镜像,java -jar arthas-boot.jar --repo-mirror aliyun --use-http)
(推荐)
第二种方式是在启动arthas的过程中,自动下载最新版的其他jar包。下载后的目录结构如下
启动(启动arthas的用户权限需要和目标进程权限保持一致)之后,选择应用java进程
$ $ java -jar arthas-boot.jar
* [1]: 35542
[2]: 71560 arthas-demo.jar
输入2,再输入回车/enter。Arthas会attach到目标进程上,并输出日志:
[INFO] Try to attach process 71560
[INFO] Attach process 71560 success.
[INFO] arthas-client connect 127.0.0.1 3658
,---. ,------. ,--------.,--. ,--. ,---. ,---.
/ O \ | .--. ''--. .--'| '--' | / O \ ' .-'
| .-. || '--'.' | | | .--. || .-. |`. `-.
| | | || |\ \ | | | | | || | | |.-' |
`--' `--'`--' '--' `--' `--' `--'`--' `--'`-----'
wiki: https://arthas.aliyun.com/doc
version: 3.0.5.20181127201536
pid: 71560
time: 2018-11-28 19:16:24
$
之后在命令行输入arthas定义的命令即可。
常用命令简介
基础命令
dashboard
显示实时信息,Thread,Memory,Rumtime
thread
展示当前最忙的前N个线程并打印堆栈
$ thread -n 3
"as-command-execute-daemon" Id=29 cpuUsage=75% RUNNABLE
at sun.management.ThreadImpl.dumpThreads0(Native Method)
at sun.management.ThreadImpl.getThreadInfo(ThreadImpl.java:440)
at com.taobao.arthas.core.command.monitor200.ThreadCommand$1.action(ThreadCommand.java:58)
at com.taobao.arthas.core.command.handler.AbstractCommandHandler.execute(AbstractCommandHandler.java:238)
at com.taobao.arthas.core.command.handler.DefaultCommandHandler.handleCommand(DefaultCommandHandler.java:67)
at com.taobao.arthas.core.server.ArthasServer$4.run(ArthasServer.java:276)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
at java.lang.Thread.run(Thread.java:745)
Number of locked synchronizers = 1
- java.util.concurrent.ThreadPoolExecutor$Worker@6cd0b6f8
"as-session-expire-daemon" Id=25 cpuUsage=24% TIMED_WAITING
at java.lang.Thread.sleep(Native Method)
at com.taobao.arthas.core.server.DefaultSessionManager$2.run(DefaultSessionManager.java:85)
"Reference Handler" Id=2 cpuUsage=0% WAITING on java.lang.ref.Reference$Lock@69ba0f27
at java.lang.Object.wait(Native Method)
- waiting on java.lang.ref.Reference$Lock@69ba0f27
at java.lang.Object.wait(Object.java:503)
at java.lang.ref.Reference$ReferenceHandler.run(Reference.java:133)
jad
反编译指定已加载类的源码
$ jad java.lang.String
ClassLoader:
Location:
/*
* Decompiled with CFR.
*/
package java.lang;
import java.io.ObjectStreamField;
import java.io.Serializable;
...
public final class String
implements Serializable,
Comparable<String>,
CharSequence {
private final char[] value;
private int hash;
private static final long serialVersionUID = -6849794470754667710L;
private static final ObjectStreamField[] serialPersistentFields = new ObjectStreamField[0];
public static final Comparator<String> CASE_INSENSITIVE_ORDER = new CaseInsensitiveComparator();
...
public String(byte[] byArray, int n, int n2, Charset charset) {
/*460*/ if (charset == null) {
throw new NullPointerException("charset");
}
/*462*/ String.checkBounds(byArray, n, n2);
/*463*/ this.value = StringCoding.decode(charset, byArray, n, n2);
}
...
redifine
redefine /tmp/Test.class
热加载class,但是不能修改、添加、删除类的field和method,包括方法参数、方法名称及返回值
注意:
- redefine命令和jad/watch/trace/monitor/tt等命令会冲突。执行完redefine之后,如果再执行上面提到的命令,则会把redefine的字节码重置。
- reset命令对redefine的类无效。如果想重置,需要redefine原始的字节码。
watch
可以用于观察方法的入参、出参、异常、当前对象等信息。使用场景比较复杂,请跳转至官方文档。
trace
方法内部调用路径,并输出方法路径上的每个节点上耗时。请参考官方文档使用
常用的场景:
- 查看代码是否执行
- 定位性能问题
stack
输出当前方法被调用的调用路径
$ stack demo.MathGame primeFactors
Press Ctrl+C to abort.
Affect(class-cnt:1 , method-cnt:1) cost in 36 ms.
ts=2018-12-04 01:32:19;thread_name=main;id=1;is_daemon=false;priority=5;TCCL=sun.misc.Launcher$AppClassLoader@3d4eac69
@demo.MathGame.run()
at demo.MathGame.main(MathGame.java:16)
一些高级用法
以上内容均来自于官方文档,总结的目的是为了降低学习成本,如有遗漏,请移至官网。