arthas的使用示例

一、热更新代码

jad,mc,retransform\redefine命令结合场景

发现线上紧急问题,排查到某个线程或定位到具体类代码bug,使用jad反编译代码,对具体bug修复,使用mc重新编译,使用retransform\redefine热更新修复问题。

# 反编译
$ jad --source-only com.example.demo.TreadTest > C:\\Users\\it06230\\Desktop\\ThreadTest.java
# 修改文件
$ vim /tmp/UserController.java
# 查找加载的 ClassLoader
$ $ sc -d *UserController | grep classLoaderHash
 classLoaderHash   6bc28484
# 编译 某个路径的文件到某个路径
$ mc -c 6bc28484 /tmp/UserController.java -d /tmp
# 热更新
$ redefine /tmp/com/example/demo/arthas/user/UserController.class
redefine success, size: 1

在这里插入图片描述
在这里插入图片描述
注意:jad反编译在99%的情况下都是准确的,但也有可能失败

二、利用多次trace排查耗时模块

利用定时任务,调用两个不定时出现延时的方法来做trace案例

timer()

->getStr(date)

​ ->sleep1()

​ ->sleep1自身可能出现耗时问题,调用的sleep2()出现耗时问题

@Scheduled(cron = "0/10 * * * * ?")
public void timer(){
    System.out.println( "测试========>" + getStr(new Date()));
}
private String getStr(Date date){
    sleep1();
    return date.toString();
}
/**
* 模拟两个随机耗时方法
*/
private void sleep1(){
    int max=1000, min=1;
    int r = (int) (Math.random()*(max-min)+min);
    if (r <= 100){
        try {
            Thread.sleep(10);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
    sleep2();
}
private void sleep2(){
    int max=1000, min=1;
    int r = (int) (Math.random()*(max-min)+min);
    if (r >= 950){
        try {
            Thread.sleep(10);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

使用trace排查思路,首先对定时任务主方法进行监控,获取到getStr方法出现耗时大于10ms的情况,并定位到sleep1方法上,通过多次定时任务的监控,发现sleep1中出现两种耗时情况,一种自身耗时,一种是调用sleep2时出现耗时大于10ms
在这里插入图片描述

三、动态修改日志级别

a.下面的方式在本地测试正常,部署服务器使用不正常(具体问题待研究)
1.查看当前日志级别logger 或 logger -n com.example.demo.ThreadTest
2.修改级别logger --name com.example.demo.ThreadTest --level info

在这里插入图片描述
在这里插入图片描述

b.使用web console测试也是正常的
1.logger -n com.example.demo.ThreadTest获取classLoaderhash和级别信息
2.使用logger -c 步骤1的hashcode --name 类全名 --lever 级别

在这里插入图片描述

有时候会提示使用sc -d查找classloader hashcode,尝试以下方式
1.使用sc -d 类全名 获取classloader hashcode信息
2.使用logger -c 步骤1获取的hashcode 查到当前日志信息
3.使用logger -c 步骤1的hashcode --name 类全名 --lever 级别

四、watch场景下方法参数及返回值监控

样例代码1:
@Scheduled(cron = "0/10 * * * * ?")
    public void timer1() {
        int max = 3, min = 0;
        int r = (int) (Math.random() * (max - min) + min);
        int result = getResult(r);
        System.out.println(result);
    }

    private int getResult(int r){
        return 10 / r;
    }

观察入参

watch com.example.demo.ThreadTest getResult “{params, returnObj}” -x 2 -b
在这里插入图片描述
监控异常

watch com.example.demo.ThreadTest timer1 “{params, throwExp}” -e -x 2
在这里插入图片描述
观察出参及返回值

watch com.example.demo.ThreadTest getResult “{params, returnObj}” -x 2
在这里插入图片描述
样例代码2:

@Scheduled(cron = "0/10 * * * * ?")
    public void timer3() {
        int max = 3, min = 0;
        int r = (int) (Math.random() * (max - min) + min);
        Map<String, Integer> map = new HashMap<>();
        map.put("a", r);
        System.out.println(getNewMap(r, map).toString());
    }

    private Map<String, Integer> getNewMap(int r, Map<String, Integer> map){
        for (Map.Entry<String, Integer> e : map.entrySet()){
            e.setValue(e.getValue() + r);
        }
        return map;
    }

调整-x的值,观察具体方法参数值

watch com.example.demo.ThreadTest getNewMap “{params, returnObj}” -x 3
在这里插入图片描述
观察当前对象的属性

watch com.example.demo.ThreadTest timer3 ‘targer’

watch com.example.demo.ThreadTest timer3 ‘targer.i’
在这里插入图片描述

五、利用tt命令对偶发异常进行监控

模拟偶发异常,当随机数为0时出现异常

@Scheduled(cron = "0/10 * * * * ?")
public void timer1(){
	int max=3, min=0;
	int r = (int) (Math.random()*(max-min)+min);
	System.out.println( 10/r);
}

使用tt -t com.example.demo.ThreadTest timer1监控
在这里插入图片描述
当监控到异常执行时,我们可以通过tt -i index命令,重现该异常执行问题

六、当一个方法被多个方法调用,或调用链很长时使用stack

stack com.example.demo.ThreadTest sleep2
在这里插入图片描述
按耗时过滤

stack com.example.demo.ThreadTest sleep2 ‘#cost>5’

七、profiler火焰图性能分析(不支持windows)

基本操作

profiler start / profiler start --duration 300(采集300s) 启动

profiler status 状态

profiler stop / profiler stop --format html / profiler stop --file ./temp/s.svg 停止

如果应用比较复杂,生成的内容很多,想只关注部分数据,可以通过 include/exclude 来过滤。比如

profiler start --include 'java/*' --include 'demo/*' --exclude '*Unsafe.park*'

在这里插入图片描述

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值