arthas入门

简介

是一款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)

一些高级用法

以上内容均来自于官方文档,总结的目的是为了降低学习成本,如有遗漏,请移至官网。

猜你喜欢

转载自blog.csdn.net/qq_28411869/article/details/115180744