Arthas常用命令

Arth常用命令

Arthas(阿尔萨斯) 能为你做什么?

Arthas 是Alibaba开源的Java诊断工具,深受开发者喜爱。

当你遇到以下类似问题而束手无策时,Arthas可以帮助你解决:

  1. 这个类从哪个 jar 包加载的?为什么会报各种类相关的 Exception?
  2. 我改的代码为什么没有执行到?难道是我没 commit?分支搞错了?
  3. 遇到问题无法在线上 debug,难道只能通过加日志再重新发布吗?
  4. 线上遇到某个用户的数据处理有问题,但线上同样无法 debug,线下无法重现!
  5. 是否有一个全局视角来查看系统的运行状况?
  6. 有什么办法可以监控到JVM的实时运行状态?
  7. 怎么快速定位应用的热点,生成火焰图?

下载

从Github Releases页下载

下载地址

启动

压缩包中提供了一个项目 artash-demo(用于演示如何使用arthas)

  1. 启动一个java项目
    java -jar arthas-demo.jar
    arthas-demo是一个简单的程序,每隔一秒生成一个随机数,再执行质因数分解,并打印出分解结果。

  2. 启动Arthas
    java -jar arthas-boot.jar
    启动arthas-boot.jar后 会出现如下界面

    $ $ java -jar arthas-boot.jar
    * [1]: 35542
      [2]: 71560 arthas-demo.jar
    

    选择我们第一步启动的项目 arthas-demo
    输入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
     
    $
    

接下来我们就可以使用命令来操作了。

常用命令

1 dasboard

dasboard命令的作用是查看当前项目的整体信息
输入dashboard,按回车/enter,会展示当前进程的信息,按ctrl+c可以中断执行。

$ 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

2 jad

使用jad命令可以查看 class文件内容,是反编译后的内容。
输入 jad命令+类全路径: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<Integer> 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<Integer> primeFactors) {
        StringBuffer sb = new StringBuffer("" + number + "=");
        Iterator<Integer> 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<Integer> primeFactors(int number) {
        if (number < 2) {
            ++this.illegalArgumentCount;
            throw new IllegalArgumentException("number is: " + number + ", need >= 2");
        }
        ArrayList<Integer> result = new ArrayList<Integer>();
        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.

3 watch

通过watch命令可以查看某个方法的返回值。
输入 watch命令+类全路径+方法名+想要监控的参数(可以是returnObj)
观察方法入参:watch demo.MathGame primeFactors “{params,returnObj}” -x 2 -b

Press Ctrl+C to abort.
Affect(class-cnt:1 , method-cnt:1) cost in 50 ms.
ts=2018-12-03 19:23:23; [cost=0.0353ms] result=@ArrayList[
    @Object[][
        @Integer[-1077465243],
    ],
    null,
]

观察方法返回值: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],
]

更多的功能可以查看进阶使用

4 quit 或 exit

如果只是退出当前的连接,可以用quit或者exit命令。Attach到目标进程上的arthas还会继续运行,端口会保持开放,下次连接时可以直接连接上。

如果想完全退出arthas,可以执行stop命令。

使用案例

1 查看当前服务中的属性信息

当我们的配置文件中配置了某些属性后,不确定项目中是否加载使用了配置后的属性植,可以使用 ognl 命令来查看。

步骤一

想办法拿到项目中 ApplicationContext 对象。ognl只获取静态属性,所以我们一般需要查找项目中是否存在静态的ApplicationContext对象。这里面我就自己创建了一个类来提供静态的ApplicationContext。

package com.greiz.demo.config;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;

@Component
public class ConfigHandler implements InitializingBean, ApplicationContextAware {
    private static ApplicationContext applicationContext;
    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.println(applicationContext.getEnvironment().getProperty("author"));
    }
    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        ConfigHandler.applicationContext = applicationContext;
    }
}
步骤二

使用ognl获取静态 ApplicationContext 属性。

ognl '#context=@com.airtimes.demo.ConfigHandle@applicationContext,#context.getEnvironment().getProperty("arthas.agent-id")'

逗号之前是获取 ApplicationContext 对象并赋值给 context。逗号后面的获取 Environment 对象中的属性。这个 “author” 属性就是application.properties 配置的,也可以是远程的配置文件。

2 替换class文件

线上环境的项目出现问题,我们想添加一些自己打印的日志,又不行重新打包重复部署,只更换某个class文件,可以使用redefine命令来解决该问题。
redefine命令:加载外部的.class文件,redefine jvm已加载的类。

方式一. 结合 jad/mc 命令使用

该方式可能出现问题,mc命令无法编译成功。

jad --source-only com.example.demo.arthas.user.UserController > /tmp/UserController.java
 
mc /tmp/UserController.java -d /tmp
 
redefine /tmp/com/example/demo/arthas/user/UserController.class
  • jad命令反编译,然后可以用其它编译器,比如vim来修改源码
  • mc命令来内存编译修改过的代码
  • 用redefine命令加载新的字节码
方式二. 使用idea编译后,替换class文件

如果mc命名无法编译class文件,那么我们就自己编译,使用idea或eclipse等开发工具。
redefine + 编译的class文件路径 如下:
redefine /tmp/com/example/demo/arthas/user/UserController.class

远程查看

生产环境中,有时没有权限操作服务器,只能远程查看信息,有两种方式来处理

方式一 生产环境启动一个arthas服务

将arthas服务部署到生产环境,然后启动,启动时需要制定ip为(0.0.0.0)否则pc无法进行长连接,然后选择要监控的进程(pc端使用浏览器连接无法选择进程,只能查看linux环境选择好的进程)。

1 将arthas服务部署到生产环境

启动,启动时需要制定ip为(0.0.0.0)

java -jar arthas-boot.jar --target-ip 0.0.0.0
2 选择要监控的进程

输入进程列表的行号,回车确定。

3 使用浏览器连接

浏览器直接访问:http://服务器ip:3658/。
IP:服务器ip
Port:3658 或 8563
_images/web-console-local.png

方式二 SpringBoot中集成Arthas

直接在项目中引入arthas,然后使用远程连接来查看项目信息。

1. 配置maven依赖:
        <dependency>
            <groupId>com.taobao.arthas</groupId>
            <artifactId>arthas-spring-boot-starter</artifactId>
            <version>${arthas.version}</version>
        </dependency>

​ 应用启动后,spring会启动arthas,并且attach自身进程。

2. 配置属性
# arthas.telnetPort设置为-1 表示使用默认
arthas.telnetPort=-1
# arthas.telnetPort设置为-1 表示使用默认
arthas.httpPort=-1
# AAAA是你这个项目的唯一	标识,随意指定
arthas.agent-id=AAAA
# ws://ip:port/ws 随意指定 ip:服务地址 port:指定一个未使用端口
arthas.tunnel-server=ws://ip:port/ws 
3 使用浏览器连接

浏览器直接访问:http://服务器ip:3658/。
IP:服务器ip
Port:3658 或 8563
_images/web-console-local.png

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值