Arthas备忘

如果应用上线后运行效果不符合预期,而又缺少必要的日志无法观测输入参数,同时线下也无法复现。大多数人应该也没有多隆大神看代码找 BUG 的神技,这个时候你就需要一款可以在线探测、热更 JVM 的神器:Arthas。Arthas 不仅可以解决上面的问题,在定位 ClassNotFoundException、程序耗时分析、线程死锁等问题方面都可以说是利器。在 Arthas 官网其实已经有很好的帮助文档了,这里更多的是做常用命令的记录,在需要的时候可以快速复制、修改、运行。

前期准备

首先需要下载 Arthas 工具,在官网链接中下载最新版即可,下载完成后进行解压。

演示用的是 Spring MVC Web 应用,用的几个类如下:

package com.roc.web.controller;

import lombok.Getter;
import lombok.Setter;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import java.util.concurrent.TimeUnit;

/**
 * 用于 arthas 的演示
 *
 * @author 鱼蛮 on 2021/12/15
 **/
@RestController
public class ArthasController {

    /**
     * 名称
     */
    @Getter
    @Setter
    private String name;

    /**
     * 锁对象
     */
    private final Object lock = new Object();

    /**
     * 用于 arthas 的演示
     *
     * @param name 输入名称
     * @return {@link String}
     */
    @GetMapping(value = "/arthas")
    public String arthas(@RequestParam("name") String name) {
        setName(name);
        return getName() + "_成功";
    }

    /**
     * 用于 arthas block 的演示
     *
     * @return {@link String}
     */
    @GetMapping(value = "/block")
    public String block() throws InterruptedException {
        new Thread(() -> {
            synchronized (lock) {
                // do nothing
            }
        }).start();
        synchronized (lock) {
            TimeUnit.SECONDS.sleep(30);
        }
        return "成功";
    }
}
/**
 * arthas 测试
 *
 * @author 鱼蛮 on 2021/12/15
 **/
public class ArthasTest {

    /**
     * 装饰数据
     *
     * @param input 输入
     * @return {@link String}
     */
    public String decorate(String input) {
        return input + "_arthas";
    }
}

首先启动我们的 Web 应用,再到 Arthas 解压出的文件夹中执行命令“java -jar arthas-boot.jar”,来启动 Arthas。

启动arthas

可以看到 Arthas 会自动检查系统中启动的 Java 应用,我们选择要进行测试的应用后回车,就可以进入 Arthas 的控制台了。

系统属性命令

dashboard 命令类似于系统的 top 命令,可以动态的列出 JVM 中的线程运行情况,及内存的分配情况、JVM 基本属性等,在观察系统整体运行情况时候是比较有用的。

jvm、sysprop、sysenv、vmoption 则可以用来查看 JVM 启动时候的系统参数、配置参数、诊断参数等。

thread

thread 命令与 JDK 自带的 jstack 命令类似,可以用来观察 JVM 中的线程运行情况,不过 thread 命令提供了更多高级功能。

## -n 3 表示找出最繁忙的 3 个
## -i 5000 代表使用率的采样间隔为 5000ms
thread -n 3 -i 5000

可以使用上面的命令找出 JVM 中最繁忙的 3 个线程。

## -b 表示找出当前阻塞其他线程的线程
thread -b

我们在浏览器中访问:http://127.0.0.1:8070/block,用于执行程序中预设的线程阻塞代码,然后再执行“thread -b”命令,可以看到如下的线程阻塞情况。

ognl

ognl 命令可以通过 ognl 表达式来帮助我们执行一些线上代码。

## -c 执行表达式的 ClassLoader 的 hashcode,默认值是 SystemClassLoader
ognl -c 18b4aac2 'new ArthasTest().decorate("zhangsan")'

sc

sc 命令用于查看 JVM 已加载的类信息。

## -d 输出当前类的详细信息
## -f 输出当前类的成员变量信息
sc -d -f com.roc.web.controller.ArthasController

sm

sm 命令用于查看 JVM 已加载类的方法信息。

## -d 展示每个方法的详细信息
sm -d ArthasTest

dump

dump 命令用于将已加载类的字节码输出到指定的目录。

 ## -d 输出类文件的目标目录
 dump -d  /Users/yuman/logs/arthas/ com.roc.web.controller.ArthasController

jad

jad 命令用于反编译指定类,这个功能可以用来帮助排查部署的代码是否有非预期代码。

## --source-only 只打印源代码,默认情况下会带有 ClassLoader 信息
jad --source-only com.roc.web.controller.ArthasController
jad com.roc.web.controller.ArthasController arthas

通过指定方法名,也可以只反编译指定的方法。

classloader

classloader 命令可以用于查看 ClassLoader 的继承树、类加载信息及进行类加载等。在排查 ClassNotFoundException 时候可以提供有效的帮助。

## -t 打印所有ClassLoader的继承树
classloader -t

## -l 按类加载实例进行统计
classloader -l

mc

mc 命令用于编译 .java 文件生成 .class 文件。

## -c 执行表达式的 ClassLoader 的 hashcode
## -d 指定输出目录
mc -c 18b4aac2 -d /Users/yuman/logs/arthas/ /Users/yuman/logs/arthas/ArthasTest.java

retransform

retransform 命令用于加载外部的 .class 文 件,替换 JVM 已加载的类。在线上缺少关键日志而又不想重启服务的时候,可以通过这个命令替换类,达到应用热更的目的。不过这种功能还是要慎用,万一搞错了很容易造成线上故障。

下面是 Arthas 官网给出的综合使用示例:

## 反编译指定类
jad --source-only com.roc.web.controller.ArthasController > /Users/yuman/logs/arthas/ArthasController.java

## 修改反编译后的类

## 编译修改后的类
mc -d /Users/yuman/logs/arthas/ /Users/yuman/logs/arthas/ArthasController.java

## 加载指定的class 替换已有的类
retransform /Users/yuman/logs/arthas/com/roc/web/controller/ArthasController.class

我们修改 arthas() 方法中 return 这行代码,增加 “ + "_retransform" ”。

@GetMapping(value={"/arthas"})
public String arthas(@RequestParam(value="name") String name) {
/*39*/         this.setName(name);
        return this.getName() + "_成功" + "_retransform";
}

当我们执行完 retransform 命令之后,再访问这个接口,可以看到变更已经生效了。

monitor

monitor 命令用于执行方法的监控,可以用来监控方法的调用次数、成功、失败次数等。

##  -c 统计周期默认120s
monitor -c 10 com.roc.web.controller.ArthasController arthas

我们连续调用 5 次 http://127.0.0.1:8070/arthas?name=zhangsan,可以看到如下的统计结果。

 ## monitor 支持条件表达式
 monitor -c 10 com.roc.web.controller.ArthasController arthas "params[0] == 'lisi'"

monitor 使用时候支持条件表达式,比如我们使用上面的命令,只有当请求参数“name=lisi”的请求才会被监控到,而其他输入参数的调用则不会被监控到。

watch

watch 命令能方便的观察到指定函数的调用情况。能观察到:返回值、抛出异常、入参。同样,watch 命令也支持条件表达式。

## -x 表示需要遍历返回值的属性深度
## {params, target, returnObj} 是观测的返回信息
watch com.roc.web.controller.ArthasController arthas "{params, target, returnObj}" -x 2

trace

trace 命令用于观测方法内部调用路径,并输出方法路径上的每个节点的耗时。在没有其他监控能力的时候,这个功能在分析接口调用的耗时情况时候非常有用。

## -n 捕获的次数 
trace com.roc.web.controller.ArthasController arthas -n 5 '#cost < 10'

stack

stack 命令用于输出方法被调用的路径。

stack com.roc.web.controller.ArthasController arthas

tt

tt 命令可以说是 watch 命令的增强版,可以对某个方法监控多次,并暂存在内存中,通过索引可以获取每次调用的现场环境。

## -t 记录每次调用个情况 
## -n 表示需要记录的次数
tt -t -n 10 com.roc.web.controller.ArthasController arthas

## -l 检索刚才的记录信息
tt -l 
检索刚才记录的信息

## 查看某个调用过程的细节,-i 查看的索引号
tt -i 1003
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,372评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,368评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,415评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,157评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,171评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,125评论 1 297
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,028评论 3 417
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,887评论 0 274
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,310评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,533评论 2 332
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,690评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,411评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,004评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,659评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,812评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,693评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,577评论 2 353

推荐阅读更多精彩内容