IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Java知识库 -> Arthas阿里开源的 Java 诊断工具 -> 正文阅读

[Java知识库]Arthas阿里开源的 Java 诊断工具

image-20210906221928133

Arthas能做什么

当我们的项目上线后可能遇到以下问题:

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

一般通过JDK自带的诊断工具去排查问题,不仅不好看而且需要记得很多的命令,而Arthas支持JDK 6+,支持Linux/Mac/Windows,采用命令行交互模式,同时提供丰富的 Tab 自动补全功能,进一步方便进行问题的定位和诊断。

官方文档:https://arthas.aliyun.com/doc/

准备

Arthas其实就是一个 jar 包,不需要安装,在GitHub可以下载,同时我也准备了Arthas 3.5.4版本(提取码:udhi)。

官方推荐使用arthas-boot,我们下载之后解压,如下:

image-20210906225109302

启动

通过以下命令启动:

java -jar arthas-boot.jar

image-20210906225836416

启动之后需要我们选择应用Java进程,我们这里选择 1 ,就成功启动了:

image-20210906230011440

常用命令

在官方文档的进阶使用介绍了 Arthas 的命令,我们也可以使用 help 查看帮助(全英文,我看不懂)。

image-20210906230509178

因为是全英文,如果英语不好的人只能望而却步了,但是看官方文档也是十分的方便。

dashboard

当前系统的实时数据面板。

注意在 arthas 中,有 tab 键填充功能,如果你只记得命令的开头几个字母,你可以 tab 补齐,所以比较好用。但是这个界面是实时刷新的,一般 5s 刷新一次,使用 q 键退出刷新(没有退出 arthas,如果要退出,使用ctrl+c )。

image-20210906232213880

thread

这个命令和 jstack 很相似,但是功能更加强大,主要是查看当前 JVM 的线程堆栈信息。

参数名称参数说明
id线程id
-n指定最忙的前 n 个线程并打印堆栈
-b找出当前阻塞其他线程的线程
-i value指定cpu使用率统计的采样间隔,单位为毫秒,默认值为200
-all显示所有匹配的线程

thread -i 1000 -n 3

每过 1000 毫秒进行采样,显示最占 CPU 时间的前 3 个线程。

image-20210907003700231

thread –b

找出阻塞当前线程的线程。

如下面一段代码:

/**
 * 类说明:演示死锁的产生,2个线程分别持有自己的锁,在不释放的情况下又想去获取对方的锁
 */
public class NormalDeadLock {

    private static Object lock1 = new Object();//第一个锁
    private static Object lock2 = new Object();//第二个锁

    //第一个拿锁的方法
    private static void lock1Do() throws InterruptedException {
        String threadName = Thread.currentThread().getName();
        synchronized (lock1) {
            System.out.println(threadName + " get lock1");
            Thread.sleep(100);
            synchronized (lock2) {
                System.out.println(threadName + " get lock2");
            }
        }
    }

    //第二个拿锁的方法
    private static void lock2Do() throws InterruptedException {
        String threadName = Thread.currentThread().getName();
        synchronized (lock2) {
            System.out.println(threadName + " get lock2");
            Thread.sleep(100);
            synchronized (lock1) {
                System.out.println(threadName + " get lock1");
            }
        }
    }

    //子线程代表lock2
    private static class Lock2 extends Thread {
        private String name;

        public Lock2(String name) {
            this.name = name;
        }

        @Override
        public void run() {
            Thread.currentThread().setName(name);
            try {
                lock1Do();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    public static void main(String[] args) throws InterruptedException {
        //主线程代表lock1
        Thread.currentThread().setName("lock1");
        Lock2 lock2 = new Lock2("lock2");
        lock2.start();
        lock2Do();
    }
}

image-20210907002931404

如果有死锁,会有红色的字提醒着,这个阻塞的线程已经被另外一个线程,如下:

image-20210907003426319

thread --state WAITING

查看处于等待状态的线程。

image-20210907003919337

jvm

查看当前JVM信息。

image-20210907004027054

jad

反编译指定已加载类的,可以查看代码是否提交更新或者在排错的时候查看别人写的代码。

命令:jad 指定的类,可用tab补齐。

image-20210907004345705

trace

使用 trace 命令可以跟踪统计方法耗时。

比如使用一个 SpringBoot 项目,控制层 getOrder 方法调用了 orderService.getOrder(orderId),这个方法中分别进行 check、service、redis、mysql 等操作。就可以根据这个命令跟踪出来哪里的耗时最长。因此trace 能方便的帮助你定位和发现因 RT(Response Time,响应时间。一般系统RT 100ms 以内是比较正常的,300ms 勉强可以接受,1s 以上的话自己看着办吧。) 高而导致的性能问题缺陷,但其每次只能跟踪一级方法的调用链路。

栗子:

@RestController
@RequestMapping("/trace")
public class TraceController {

    @RequestMapping("/getOrder")
    public String getOrder(@RequestParam("orderId") String order) {
        StringBuffer buffer = new StringBuffer();
        //模拟check操作
        String check = check(order);
        String service = service(order);
        String redis = redis(order);
        String mysql = mysql(order);
        buffer.append(check).append(service).append(redis).append(mysql);
        return buffer.toString();
    }

    //检查订单编号是否正确
    public String check(String order) {
        try {
            Thread.sleep(50);
            return "订单编号check正常</br>";
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return "fail";
    }

    //模拟业务操作
    public String service(String order) {
        try {
            Thread.sleep(60);
            return "通过订单编号业务操作service正常</br>";
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return "fail";
    }

    //模拟redis查询
    public String redis(String order) {
        try {
            Thread.sleep(30);
            return "通过订单编号查询redis正常</br>";
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return "fail";
    }

    //模拟mysql查询
    public String mysql(String order) {
        try {
            Thread.sleep(30);
            return "通过订单编号查询mysql正常</br>";
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return "fail";
    }
}

访问:http://localhost:8080/trace/getOrder?orderId=2

image-20210907190329284

通过trace命令查看:

image-20210907190010835

monitor

方法执行监控。如每 5 秒统计一次某个类的某个方法的方法执行情况。

image-20210907191402403

watch

观察方法的入参出参信息。如:返回值、抛出异常、入参。

还是上面的代码,我们查看方法的入参和返回值可以这样:

watch cn.javatv.demo.controller.TraceController getOrder '{params[0],returnObj}'

image-20210907192136186

总结

Arthas 是一个很优秀的 java 诊断工具,无论是安装还是使用都很简洁,这里只是列出了部分,如果你需要学习使用,建议查看官方文档和手动尝试。

Arthas命令列表:

image-20210907195318674

参考:arthas使用介绍

  Java知识库 最新文章
计算距离春节还有多长时间
系统开发系列 之WebService(spring框架+ma
springBoot+Cache(自定义有效时间配置)
SpringBoot整合mybatis实现增删改查、分页查
spring教程
SpringBoot+Vue实现美食交流网站的设计与实
虚拟机内存结构以及虚拟机中销毁和新建对象
SpringMVC---原理
小李同学: Java如何按多个字段分组
打印票据--java
上一篇文章      下一篇文章      查看所有文章
加:2021-09-10 23:55:15  更:2021-09-10 23:55:34 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/23 17:06:22-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码