• Java 诊断工具 Arthas 教程学习笔记


    Java 诊断利器 Arthas,是阿里的一款开源工具。Github-alibaba/arthas 上可以看到它的介绍。了解它,主要是最近对分析 Java 错误堆栈比较感兴趣,机缘巧合看到了它。

    本文记录的内容,就是基于它官网的文档摘抄的,涉及的截图可能由于篇幅有限,不是很完整,建议按照官方文档,实操一遍。

    基础教程

    启动 arthas-boot

    wget https://alibaba.github.io/arthas/arthas-boot.jar
    java -jar arthas-boot.jar --target-ip 0.0.0.0
    

    默认情况下, arthas server 侦听的是 127.0.0.1 这个IP,如果希望远程可以访问,可以使用--target-ip 的参数

    arthas-bootArthas 的启动程序,它启动后,会列出所有的 Java 进程,输入需要诊断的目标进程序号即可。

    Arthas支持通过 Web Socket来连接。

    当在本地启动时,可以访问 http://127.0.0.1:8563/ ,通过浏览器来使用 Arthas。

    输入 help 可以看到常用的帮助命令:

    arthas-boot.jar 支持很多参数,可以执行 java -jar arthas-boot.jar -h 查看

    dashboard

    • dashboard 命令可以查看系统的实时数据面板。
    • qctrl+c 可以退出数据面展示。

    数据说明:

    • ID: Java级别的线程ID,注意这个ID不能跟jstack中的nativeID一一对应
    • NAME: 线程名
    • GROUP: 线程组名
    • PRIORITY: 线程优先级, 1~10之间的数字,越大表示优先级越高
    • STATE: 线程的状态
    • CPU%: 线程消耗的cpu占比,采样100ms,将所有线程在这100ms内的cpu使用量求和,再算出每个线程的cpu使用占比。
    • TIME: 线程运行总时间,数据格式为分:秒
    • INTERRUPTED: 线程当前的中断位状态
    • DAEMON: 是否是daemon线程

    thread

    thread 1 打印线程 ID 1 的栈

    Arthas 支持管道命令,可以利用 thread 1|grep 'main(' 查找 main class

    查看 CPU 使用率 top n 的线程的栈,当前最忙的前 n 个线程:

    thread -n 3
    

    查看 5 秒内的 CPU 使用率 top n 的线程栈:

    thread -n 3 -i 5000
    

    -i 指定 CPU 占比统计的采样间隔,单位为毫秒

    查看线程是否有阻塞:

    thread -b
    

    有时候我们发现应用卡住了, 通常是由于某个线程拿住了某个锁, 并且其他线程都在等待这把锁造成的。 为了排查这类问题,此时使用 -b 参数,找到罪魁祸首。

    注意, 目前只支持找出synchronized关键字阻塞住的线程, 如果是java.util.concurrent.Lock, 目前还不支持

    sc -- 查找 JVM 加载类

    Search-Class 的简写,这个命令能搜索出所有已经加载到 JVM 中的 Class 信息,sc -d *MathGame

    如果搜索的是接口,还会搜索所有的实现类。比如查看所有的 Filter 实现类:

    sc javax.servlet.Filter
    

    -d 参数可以打印出类加载的具体信息,方便定位类加载问题

    sc 支持通配符,比如搜索所有的 StringUtils

    sc *StringUtils
    

    打印类的 Field 信息:

    sc -d -f demo.MathGame
    

    sm -- 查看已加载类的方法信息

    Search-Method 的简写,这个命令能搜索出所有已经加载了 Class 信息的方法信息。

    sm 命令只能看到由当前类所声明 (declaring) 的方法,父类则无法看到

    查看 String 类的全部方法:

    sm java.lang.String
    

    查看具体方法的信息:

    sm java.lang.String toString
    

    通过 -d 参数可以打印函数的具体属性,展示每个方法的详细信息():

    sm -d java.math.RoundingMode
    

    jad

    通过 jad 命令反编译代码:

    jad demo.MatthGame
    

    Watch

    watch 命令可以查看函数的:

    • 参数
    • 返回值
    • 异常信息
    watch demo.MathGame primeFactors returnObj
    

    watch com.example.demo.arthas.user.UserController * '{params, throwExp}' -x 2
    
    1. 第一个参数是类名,支持通配
    2. 第二个参数是函数名,支持通配
    3. 第三个参数是定义返回值
    4. -x 2 是为了将结果展开

    返回值表达式实际是一个 ognl 表示,支持一些内置对象:

    • loader
    • clazz
    • method
    • target
    • params
    • returnObj
    • throwExp
    • isBefore
    • isThrow
    • isReturn

    watch命令支持按请求耗时进行过滤:

    watch com.example.demo.arthas.user.UserController * '{params, returnObj}' '#cost>200'
    

    Arthas在 watch/trace 等命令时,实际上是修改了应用的字节码,插入增强的代码。显式执行 reset 命令,可以清除掉这些增强代码

    退出 Arthas

    exitquit 可以退出 Arthas

    退出 Arthas 之后,还可以再次使用 java -jar arthas-boot.jar 来链接

    exit/quit 命令只是退出当前 session,arthas server 还在目标进程中运行,shutdown 命令才能完全退出 Arthas。

    进阶

    启动 Spring Boot Demo

    wget https://github.com/hengyunabc/katacoda-scenarios/raw/master/demo-arthas-spring-boot.jar
    java -jar demo-arthas-spring-boot.jar
    

    启动 arthas-boot

    wget https://alibaba.github.io/arthas/arthas-boot.jar
    java -jar arthas-boot.jar --target-ip 0.0.0.0
    

    就像基础教程说过的,选择目标进程

    查看 JVM 信息

    sysprop

    查看当前 JVM 的系统属性(System Property)

    • sysprop 打印所有 System Properties
    • 指定单个 key:sysprop java.version
    • 通过 grep 过滤:sysprop|grep user
    • 设置新的value: sysprop testKey testValue

    sysenv

    sysenv 命令查看当前 JVM 的环境属性(System Environment Variables)

    也是支持查看单个环境变量值的:

    sysenv USER
    

    jvm

    jvm 命令可以打印 JVM 的各种信息

    Thread 相关:

    • COUNT: JVM 当前活跃的线程数
    • DAEMON-COUNT: JVM 当前活跃的守护线程数
    • PEAK-COUNT: 从J VM 启动开始曾经活着的最大线程数
    • STARTED-COUNT: 从 JVM 启动开始总共启动过的线程次数
    • DEADLOCK-COUNT: JVM 当前死锁的线程数

    文件描述符相关:

    • MAX-FILE-DESCRIPTOR-COUNT:JVM 进程最大可以打开的文件描述符数
    • OPEN-FILE-DESCRIPTOR-COUNT:JVM 当前打开的文件描述符数

    ognl

    获取静态类的静态字段:

    ognl '@demo.MathGame@random'
    

    具体,查看执行ognl表达式

    trace

    方法内部调用路径,并输出方法路径上的每个节点上耗时

    trace 命令能主动搜索 class-pattern/method-pattern 对应的方法调用路径,渲染和统计整个调用链路上的所有性能开销和追踪调用链路

    参数名称 参数说明
    class-pattern 类名表达式匹配
    method-pattern 方法名表达式匹配
    condition-express 条件表达式
    [E] 开启正则表达式匹配,默认为通配符匹配
    [n:] 命令执行次数
    #cost 方法执行耗时

    很多时候我们只想看到某个方法的 rt 大于某个时间之后的 trace 结果,现在 Arthas 可以按照方法执行的耗时来进行过滤了,例如 trace *StringUtils isBlank '#cost>100' 表示当执行时间超过 100ms 的时候,才会输出 trace 的结果。

    watch/stack/trace 这个三个命令都支持 #cost

    trace 函数:

    $ trace demo.MathGame run
    Press Ctrl+C to abort.
    Affect(class-cnt:1 , method-cnt:1) cost in 42 ms.
    `---ts=2018-12-04 00:44:17;thread_name=main;id=1;is_daemon=false;priority=5;TCCL=sun.misc.Launcher$AppClassLoader@3d4eac69
        `---[10.611029ms] demo.MathGame:run()
            +---[0.05638ms] java.util.Random:nextInt()
            +---[10.036885ms] demo.MathGame:primeFactors()
            `---[0.170316ms] demo.MathGame:print()
    

    过滤掉 jdk 的函数:

    $ trace -j  demo.MathGame run
    Press Ctrl+C to abort.
    Affect(class-cnt:1 , method-cnt:1) cost in 31 ms.
    `---ts=2018-12-04 01:09:14;thread_name=main;id=1;is_daemon=false;priority=5;TCCL=sun.misc.Launcher$AppClassLoader@3d4eac69
        `---[5.190646ms] demo.MathGame:run()
            +---[4.465779ms] demo.MathGame:primeFactors()
            `---[0.375324ms] demo.MathGame:print()
    
    • -j: jdkMethodSkip, skip jdk method trace

    trace 在执行的过程中本身是会有一定的性能开销,在统计的报告中并未像 JProfiler 一样预先减去其自身的统计开销

    stack

    输出当前方法被调用的调用路径

    很多时候我们都知道一个方法被执行,但这个方法被执行的路径非常多,或者你根本就不知道这个方法是从那里被执行了,此时你需要的是 stack 命令。

    参数名称 参数说明
    class-pattern 类名表达式匹配
    method-pattern 方法名表达式匹配
    condition-express 条件表达式
    [E] 开启正则表达式匹配,默认为通配符匹配
    [n:] 执行次数限制

    据执行时间来过滤:

    $ stack demo.MathGame primeFactors '#cost>5'
    Press Ctrl+C to abort.
    Affect(class-cnt:1 , method-cnt:1) cost in 35 ms.
    ts=2018-12-04 01:35:58;thread_name=main;id=1;is_daemon=false;priority=5;TCCL=sun.misc.Launcher$AppClassLoader@3d4eac69
        @demo.MathGame.run()
            at demo.MathGame.main(MathGame.java:16)
    

    Arthas 使用技巧

    • 每个命令,都可以加上 -h 来查看对应的帮助信息,例如:sc -h
    • Tab 自动补全,例如:sysprop java. 按下 Tab 键,会补全对应的 key
    • 支持常见的命令行快捷键,比如 ctrl+a/e,更多输入 keymap 查看
    • 历史命令补全,输入一半时,按下Up/↑Down/↓ 来匹配,例如 sysprop ja 之后,按下 会帮你自动补全
    • 管道命令支持,例如 sysprop | wc -l

    参考

  • 相关阅读:
    OC之runtime面试题(一)
    OC之runtime的(isKindOfClass和isMemberOfClass)
    OC之runtime(super)
    OC中的__block修饰符
    iOS录音及播放
    webpack5升级过程遇到的一些坑?
    (转)iOS工具--CocoaPods 安装使用总结
    iOS学习--NSObject详解
    iOS学习--通过ipa包如何获取图片资源
    ‘A downloaded software component is corrupted and will not be used. ‘ while publish an iOS app to apple store via Xcode
  • 原文地址:https://www.cnblogs.com/michael-xiang/p/10777756.html
Copyright © 2020-2023  润新知