arthas神器--watch查看方法入参、出参、类成员变量

目录

一、原因

二、watch主要功能

三、使用

1、下载

2、测试类代码

四、示例

1、查看方法出参和返回值

2、查看类对象的属性

3、过滤不需要的请求

4、没有办法输出局部变量的值

5、查看方法耗时

五、arthas idea插件


一、原因

        曾经,线上出了问题又定位不到问题原因,就开始抓耳挠腮,一遍一遍仔细看代码,到底是哪里可能出错了呢?然后在可能出错的地方加上日志,然后重新部署,再看输出日志;发现不行,还需要输出这个方法中的这个参数,然后再重新部署;一遍一遍循环往复,甚是繁琐。心想就没有一个想debug那样可以在线时时查看的功能么?

        自从我接触了arthas,我被它强大的功能所折服。当我第一次看到同事使用arthas输出线上程序中任意方法的请求参数时心中一惊,还有这么神奇的工具呢?自此开启了我对arthas的崇拜之路。

        但是刚开始感觉还是会有点繁琐,不会过滤请求、不会看成员变量,有时候想看方法中某一参数的值,但是又不知道该怎么看,还是很苦恼。

        因此决定仔细学习一下arthas到底有哪些功能,都能做什么,这么好用的神器,不会用不是白白可惜了。

二、watch主要功能

1、查看方法入参、返回值

2、过滤无用的输出

3、查看类中的成员变量

4、无法查看方法中的局部变量

首先附上官方文档,更详细、更多的资料可以查看官方文档

watch — Arthas 3.6.2 文档

参数名称参数说明
class-pattern类名表达式匹配
method-pattern方法名表达式匹配
express观察表达式
condition-express条件表达式
[b]方法调用之前观察
[e]方法异常之后观察
[s]方法返回之后观察
[f]方法结束之后(正常返回和异常返回)观察
[E]开启正则表达式匹配,默认为通配符匹配
x指定输出结果的属性遍历深度,默认为 1
n指定执行次数

        这部分可以先跳过,看完下面例子回过头来再看,这里重点要说明的是观察表达式,观察表达式的构成主要由 ognl 表达式组成,所以你可以这样写"{params,returnObj,target,throwExp}",只要是一个合法的 ognl 表达式,都能被正常支持。

params:表示方法入参,可以通过params[0]获取指定位置的参数,可以用于过滤请求条件使用

returnObj:表示方法返回参数;

target:表示类对象,可以通过target查看成员变量的值;

throwExp:表示异常;

特别说明

  • watch 命令定义了4个观察事件点,即 -b 方法调用前,-e 方法异常后,-s 方法返回后,-f 方法结束后

  • 4个观察事件点 -b-e-s 默认关闭,-f 默认打开,当指定观察点被打开后,在相应事件点会对观察表达式进行求值并输出

  • 这里要注意方法入参方法出参的区别,有可能在中间被修改导致前后不一致,除了 -b 事件点 params 代表方法入参外,其余事件都代表方法出参

  • 当使用 -b 时,由于观察事件点是在方法调用前,此时返回值或异常均不存在

三、使用

1、windows下载

下载地址

https://alibaba.github.io/arthas/arthas-boot.jar

2、linux下载

wget https://arthas.aliyun.com/arthas-boot.jar

直接用java -jar的方式启动,首先启动我们的demo项目,然后在启动arthas

2、测试类代码

DemoController类

package com.demo.controller;

import com.demo.model.UserModel;
import com.demo.service.DemoService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class DemoController {

    @Autowired
    private DemoService demoService;

    @RequestMapping("/user")
    @GetMapping
    public String list(String name){
        UserModel userModel = new UserModel();
        userModel.setName(name);
        return demoService.getUser(name, userModel);
    }

}

DemoService类

package com.demo.service;

import com.demo.model.UserModel;
import org.springframework.stereotype.Service;

@Service
public class DemoService {

    private static String PATH = "/home";

    private String user;

    public String getUser(String name, UserModel userModel) {
        user = "zhangsan";
        return userModel.getName();
    }
}

UserModel类

package com.demo.model;

import lombok.Data;

@Data
public class UserModel {

    public UserModel(){}

    public UserModel(String id, String name, Integer age) {
        this.id = id;
        this.name = name;
        this.age = age;
    }

    private String id;

    private String name;

    private Integer age;

}

四、示例

1、查看方法入参和返回值

watch com.demo.service.DemoService getUser '{params,returnObj}' -x 3

2、查看类对象的属性

watch com.demo.service.DemoService getUser 'target' -x 2

查看类中静态变量,PATH为类中的静态成员变量

getstatic com.demo.service.DemoService PATH  -x 2

3、过滤不需要的请求

        实际使用中会有不相关的请求调用我们的目标方法,可以通过添加过滤条件,只输出我们自己请求的日志,params[0]=='demo'表示只有当第一个参数等于demo时才输出。

watch com.demo.service.DemoService getUser "{params,returnObj}" "params[0]=='demo'" -x 4

        当我们请求参数为demo1时,控制台并没有输出日志,当参数为demo时,可以正常输出。

采用参数UserModel对象中的属性过滤也是可以的,如下面示例:

watch com.demo.service.DemoService getUser "{params,returnObj}" "params[1].name=='demo'" -x 4

4、没有办法输方法中出局部变量的值(这点需要强调一下)

public void A(){
    String index = 0;
    String b = B();
    String index = b;
}

public String B(){
    return "B";
}

        比如上边的,想查看index最后的值是不可以的,我们只能通过拦截B()方法获取到b的值,却没有办法获取不是通过方法调用赋值的局部变量。

        很多时候,我们想输出方法中某一个变量的值,但是到目前为止还没有找到好的方法,只能获取赋值给这个参数的方法的返回值来确定,这是一个比较遗憾的地方。

        watch 虽然很方便和灵活,但需要提前想清楚观察表达式的拼写,这对排查问题而言要求太高,因为很多时候我们并不清楚问题出自于何方,只能靠蛛丝马迹进行猜测。

        这个时候如果能记录下当时方法调用的所有入参和返回值、抛出的异常会对整个问题的思考与判断非常有帮助。

        同时还有更多命令和方法协同使用来定位问题,比如:

1)trace获得一个方法的调用路径;

2)tt: 记录下指定方法每次调用的入参和返回信息,并能对这些不同的时间下调用进行观测。

        我也还在进一步学习、使用中,以后有了更多的总结再来补充。

5、查看方法耗时

        当遇到执行时间比较长的接口,我们想知道时间到底消耗在哪里,但是手动去输出每个方法又太繁琐,这时候arthas告诉你,让我来!一个trace命令轻松搞定。

        比如我们想查看DemoController#list()方法的内部耗时,只需要执行下面的命令,就可以看的一清二楚。

trace com.demo.controller.DemoController list

五、arthas idea插件

        有了arthas这种神器可以线上输出日志,但是watch语法还是不够简单,因此Idea arthas 插件就此横空出世,插件安装成功后,只需要将光标放置在具体的类、字段、方法上面 右键选择需要执行的命令,部分会有窗口弹出、根据界面操作获取命令;部分直接获取命令复制到了剪切板 ,自己启动arthas 后粘贴即可执行。

复制出来的命令:

watch com.demo.service.DemoService getUser '{params,returnObj,throwExp}' -v -n 5 -x 3 '1==1'

  • 15
    点赞
  • 78
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
为什么要学JVM1、一切JAVA代码都运行在JVM之上,只有深入理解虚拟机才能写出更强大的代码,解决更深层次的问题。2、JVM是迈向高级工程师、架构师的必备技能,也是高薪、高职位的不二选择。3、同时,JVM又是各大软件公司笔试、面试的重中之重,据统计,头部的30家互利网公司,均将JVM作为笔试面试的内容之一。4、JVM内容庞大、并且复杂难学,通过视频学习是最快速的学习手段。课程介绍本课程包含11个大章节,总计102课时,无论是笔试、面试,还是日常工作,可以让您游刃有余。第1章 基础入门,从JVM是什么开始讲起,理解JDK、JRE、JVM的关系,java的编译流程和执行流程,让您轻松入门。第2章 字节码文件,深入剖析字节码文件的全部组成结构,以及javap和jbe可视化反解析工具的使用。第3章 的加载、解释、编译,本章节带你深入理解加载器的分、范围、双亲委托策略,自己手写加载器,理解字节码解释器、即时编译器、混合模式、热点代码检测、分层编译等核心知识。第4章 内存模型,本章节涵盖JVM内存模型的全部内容,程序计数器、虚拟机栈、本地方法栈、方法区、永久代、元空间等全部内容。第5章 对象模型,本章节带你深入理解对象的创建过程、内存分配的方法、让你不再稀里糊涂。第6章 GC基础,本章节是垃圾回收的入门章节,带你了解GC回收的标准是什么,什么是可达性分析、安全点、安全区,四种引用型的使用和区别等等。第7章 GC算法与收集器,本章节是垃圾回收的重点,掌握各种垃圾回收算法,分代收集策略,7种垃圾回收器的原理和使用,垃圾回收器的组合及分代收集等。第8章 GC日志详解,各种垃圾回收器的日志都是不同的,怎么样读懂各种垃圾回收日志就是本章节的内容。第9章 性能监控与故障排除,本章节实战学习jcmd、jmx、jconsul、jvisualvm、JMC、jps、jstatd、jmap、jstack、jinfo、jprofile、jhat总计12种性能监控和故障排查工具的使用。第10章 阿里巴巴Arthas在线诊断工具,这是一个特别小惊喜,教您怎样使用当前最火热的arthas调优工具,在线诊断各种JVM问题。第11章 故障排除,本章会使用实际案例讲解单点故障、高并发和垃圾回收导致的CPU过高的问题,怎样排查和解决它们。课程资料课程附带配套项目源码2个159页高清PDF理论篇课件1份89页高清PDF实战篇课件1份Unsafe源码PDF课件1份class_stats字段说明PDF文件1份jcmd Thread.print解析说明文件1份JProfiler内存工具说明文件1份字节码可视化解析工具1份GC日志可视化工具1份命令行工具cmder 1份学习方法理论篇部分推荐每天学习2课时,可以在公交地铁上用手机进行学习。实战篇部分推荐对照视频,使用配套源码,一边练习一遍学习。课程内容较多,不要一次性学太多,而是要循序渐进,坚持学习。      

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值