Jast blog Jast blog
首页
  • 《Ambari自定义开发教程》笔记
  • 《CDH教程》笔记
  • 《ClickHouse教程》笔记
  • 《HDFS教程》笔记
  • 《DolphinScheduler教程》笔记
  • 《Hbase教程》笔记
  • 《Iceberg教程》笔记
  • 《Hive教程》笔记
  • 《Flume教程》笔记
  • 《Kafka教程》笔记
  • 《Impala教程》笔记
  • 《Hue教程》笔记
  • 《Spark教程》笔记
  • 《Flink教程》笔记
  • 《Phoenix教程》笔记
  • 《ElasticSearch教程》笔记
  • 《Kylin教程》笔记
  • 《Storm教程》笔记
  • 《Yarn教程》笔记
  • 《Presto教程》笔记
  • 《图数据库教程》笔记
  • 《Kerberos教程》笔记
  • 《Maxwell教程》笔记
  • 《MinIO教程》笔记
  • 《DataX教程》笔记
  • 《Superset教程》笔记
  • 《IOTDB教程》笔记
  • 《大数据相关》笔记
  • 《PaddleNLP教程》笔记
  • 《Nginx教程》笔记
  • 《Java技术文档》
  • 《Maven教程》笔记
  • 《IDEA使用教程》
  • 学习
  • 面试
  • 心情杂货
  • 实用技巧
  • 友情链接
关于
收藏
  • 分类
  • 标签
  • 归档

Jast-zsh

如果你知道你要去哪里,全世界都会给你让路。
首页
  • 《Ambari自定义开发教程》笔记
  • 《CDH教程》笔记
  • 《ClickHouse教程》笔记
  • 《HDFS教程》笔记
  • 《DolphinScheduler教程》笔记
  • 《Hbase教程》笔记
  • 《Iceberg教程》笔记
  • 《Hive教程》笔记
  • 《Flume教程》笔记
  • 《Kafka教程》笔记
  • 《Impala教程》笔记
  • 《Hue教程》笔记
  • 《Spark教程》笔记
  • 《Flink教程》笔记
  • 《Phoenix教程》笔记
  • 《ElasticSearch教程》笔记
  • 《Kylin教程》笔记
  • 《Storm教程》笔记
  • 《Yarn教程》笔记
  • 《Presto教程》笔记
  • 《图数据库教程》笔记
  • 《Kerberos教程》笔记
  • 《Maxwell教程》笔记
  • 《MinIO教程》笔记
  • 《DataX教程》笔记
  • 《Superset教程》笔记
  • 《IOTDB教程》笔记
  • 《大数据相关》笔记
  • 《PaddleNLP教程》笔记
  • 《Nginx教程》笔记
  • 《Java技术文档》
  • 《Maven教程》笔记
  • 《IDEA使用教程》
  • 学习
  • 面试
  • 心情杂货
  • 实用技巧
  • 友情链接
关于
收藏
  • 分类
  • 标签
  • 归档
  • Freemarker模板使用
  • Java项目通过Log4j将日志发送到Kafka
  • Java Maven中自动代码检查插件
  • Protobuf详细介绍
  • 提升开发效率:JCommander高效Java命令行参数解析利器
  • 36k Star!Arthas Java开发者的故障排查利器
    • Arthas 与其他工具对比
    • 快速启动 Arthas
    • Dashboard 监控
      • 查看 CPU 占用线程
      • 找出当前阻塞其他线程的线程
      • 类进行反编译
      • 查看类的基础信息
      • 查看类调用方法的堆栈信息
      • 分析哪些方法执行慢
      • 监听某一个方法的返回值
      • 获取运行中类的的字段
      • 方法执行监控
    • 环境变量与系统属性查看
      • 查看环境变量
      • 查看当前 JVM 的系统属性(System Property)
      • 火焰图生成-profiler
    • 常见问题
      • target process not responding or HotSpot VM not loaded
  • 高级单元测试中的 Mockito 使用指南
  • Java代码覆盖率工具
  • Jar包源码修改
  • 《Java技术文档》
Jast-zsh
2024-11-06
目录

36k Star!Arthas Java开发者的故障排查利器

# Arthas:Java 程序问题定位神器

image-20241028135043535

Arthas 是 Alibaba 开发的强大 Java 诊断工具,提供了一系列实用的命令用于探查和优化 Java 应用的运行情况。本文将带您详细了解如何使用 Arthas 进行分析、诊断和优化 Java 应用,以便快速定位并解决性能瓶颈和应用故障。

# Arthas 与其他工具对比

image-20241028134602877

# 快速启动 Arthas

在启动 Arthas 过程中,我们可以选择需要分析的进程。选择 Java 进程后,Arthas 将自动下载并附加到指定进程上。

$ java -jar arthas-boot.jar --repo-mirror aliyun --use-http
[INFO] JAVA_HOME: /opt/jdk1.8.0_151/jre
[INFO] arthas-boot version: 4.0.2
* [1]: 11490 kafka.Kafka
1	            
...                                                                 
pid        11490          

[arthas@11490]$ 
1
2
3
4
5
6
7
8
9

Arthas 启动后,可直接通过命令行或 Web 界面(http://localhost:3658)进行操作。

# Dashboard 监控

Dashboard 提供了 Java 应用的 CPU、内存、线程等运行状态的实时监控,方便快速定位问题所在。

输入dashborad

[arthas@11490]$ dashborad
1

img

# 查看 CPU 占用线程

当应用负载过高时,我们可以用 thread -n 命令查看占用 CPU 比较高的线程:

此命令将列出 CPU 占用率最高的两个线程,帮助我们识别出 CPU 密集型线程及其具体操作。

image-20241028112951939

# 找出当前阻塞其他线程的线程

在 Java 应用中,可能存在某些线程阻塞其他线程的情况。thread -b 命令可以帮助我们快速定位阻塞线程。

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

image-20241028132912211

# 类进行反编译

比如我们通过Arthas分析到某一个类有问题,我们想看类的代码是什么,可以使用该方法。

[arthas@11490]$ jad org.apache.kafka.common.network.Selector

image-20241028113320310

# 查看类的基础信息

sc -d ${类名}

image-20241028113432885

# 查看类调用方法的堆栈信息

我们可以使用 stack 命令,实时追踪指定类的方法调用堆栈,找出调用链和执行顺序。 当有方法调用了org.apache.kafka.common.network.Selector select就会打印出详细信息

[arthas@11490]$ stack org.apache.kafka.common.network.Selector select 
Press Q or Ctrl+C to abort.
Affect(class count: 1 , method count: 1) cost in 1332 ms, listenerId: 2
ts=2024-10-28 21:36:14.166;thread_name=ReplicaFetcherThread-0-1001;id=297787;is_daemon=false;priority=5;TCCL=sun.misc.Launcher$AppClassLoader@764c12b6
    @org.apache.kafka.common.network.Selector.select()
        at org.apache.kafka.common.network.Selector.poll(Selector.java:409)
        at org.apache.kafka.clients.NetworkClient.poll(NetworkClient.java:510)
        at org.apache.kafka.clients.NetworkClientUtils.isReady(NetworkClientUtils.java:41)
        at org.apache.kafka.clients.NetworkClientUtils.awaitReady(NetworkClientUtils.java:64)
        at kafka.server.ReplicaFetcherBlockingSend.sendRequest(ReplicaFetcherBlockingSend.scala:91)
        at kafka.server.ReplicaFetcherThread.fetch(ReplicaFetcherThread.scala:240)
        at kafka.server.ReplicaFetcherThread.fetch(ReplicaFetcherThread.scala:43)
        at kafka.server.AbstractFetcherThread.processFetchRequest(AbstractFetcherThread.scala:149)
        at kafka.server.AbstractFetcherThread.doWork(AbstractFetcherThread.scala:114)
        at kafka.utils.ShutdownableThread.run(ShutdownableThread.scala:82)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

# 分析哪些方法执行慢

使用 trace 命令可以追踪方法的执行情况,分析哪些方法在执行中消耗了较多时间,从而定位性能瓶颈。

trace

# 监听某一个方法的返回值

通过 watch 命令可以监听指定方法的返回值,例如:

[arthas@11490]$ watch org.apache.kafka.common.network.Selector select
1

此命令会在每次 select 方法执行完成时,返回其结果数据,以供调试。

method=org.apache.kafka.common.network.Selector.select location=AtExit
ts=2024-10-28 21:41:11.760; [cost=0.26099ms] result=@ArrayList[
    @Object[][isEmpty=false;size=1],
    @Selector[org.apache.kafka.common.network.Selector@3c7b65a1],
    @Integer[1],
]
method=org.apache.kafka.common.network.Selector.select location=AtExit
ts=2024-10-28 21:41:11.761; [cost=0.04802ms] result=@ArrayList[
    @Object[][isEmpty=false;size=1],
    @Selector[org.apache.kafka.common.network.Selector@3c7b65a1],
    @Integer[1],
]
1
2
3
4
5
6
7
8
9
10
11
12

# 获取运行中类的的字段

调用静态函数:

$ ognl '@java.lang.System@out.println("hello")'
null
1
2

获取静态类的静态字段:

$ ognl '@demo.MathGame@random'
@Random[
    serialVersionUID=@Long[3905348978240129619],
    seed=@AtomicLong[125451474443703],
    multiplier=@Long[25214903917],
    addend=@Long[11],
    mask=@Long[281474976710655],
    DOUBLE_UNIT=@Double[1.1102230246251565E-16],
    BadBound=@String[bound must be positive],
    BadRange=@String[bound must be greater than origin],
    BadSize=@String[size must be non-negative],
    seedUniquifier=@AtomicLong[-3282039941672302964],
    nextNextGaussian=@Double[0.0],
    haveNextNextGaussian=@Boolean[false],
    serialPersistentFields=@ObjectStreamField[][isEmpty=false;size=3],
    unsafe=@Unsafe[sun.misc.Unsafe@28ea5898],
    seedOffset=@Long[24],
]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

执行多行表达式,赋值给临时变量,返回一个 List:

$ ognl '#value1=@System@getProperty("java.home"), #value2=@System@getProperty("java.runtime.name"), {#value1, #value2}'
@ArrayList[
    @String[/opt/java/8.0.181-zulu/jre],
    @String[OpenJDK Runtime Environment],
]
1
2
3
4
5

# 方法执行监控

image-20241028114940933

监控维度说明:

监控项 说明
timestamp 时间戳
class Java 类
method 方法(构造方法、普通方法)
total 调用次数
success 成功次数
fail 失败次数
rt 平均 RT
fail-rate 失败率

# 环境变量与系统属性查看

在 Java 应用中,系统属性和环境变量影响着应用的运行配置。Arthas 提供了 sysenv 和 sysprop 命令以供查看和修改。

# 查看环境变量

sysenv

image-20241028115628445

查看单个环境变量

$ sysenv USER
USER=admin
1
2

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

sysprop
1

image-20241028115757185

查看,修改单个属性

支持通过TAB键自动补全

$ sysprop user.country
user.country=US
$ sysprop user.country CN
Successfully changed the system property.
user.country=CN
1
2
3
4
5

# 火焰图生成-profiler

启动 profiler

默认情况下,生成的是 cpu 的火焰图,即 event 为cpu。可以用--event参数指定其他性能分析模式,参考:https://arthas.aliyun.com/doc/profiler.html#profiler-%E6%94%AF%E6%8C%81%E7%9A%84-events。

$ profiler start
Started [cpu] profiling
1
2

获取已采集的 sample 的数量

$ profiler getSamples
23
1
2

查看 profiling 状态

$ profiler status
[cpu] profiling is running for 4 seconds
1
2

停止 profiler

生成火焰图格式结果

默认情况下,结果是 Flame Graph在新窗口打开 (opens new window) 格式的 html 文件,也可以用 -o 或 --format 参数指定其他内容格式,包括 flat、traces、collapsed、flamegraph、tree、jfr。

$ profiler stop --format flamegraph
profiler output file: /tmp/test/arthas-output/20211207-111550.html
OK
1
2
3

在--file参数指定的文件名后缀为 html 或 jfr 时,文件格式可以被推断出来。比如--file /tmp/result.html 将自动生成火焰图。

效果如下

img

# 常见问题

# target process not responding or HotSpot VM not loaded

[ERROR] Start arthas failed, exception stack trace: 
com.sun.tools.attach.AttachNotSupportedException: Unable to open socket file: target process not responding or HotSpot VM not loaded
	at sun.tools.attach.LinuxVirtualMachine.<init>(LinuxVirtualMachine.java:106)
	at sun.tools.attach.LinuxAttachProvider.attachVirtualMachine(LinuxAttachProvider.java:78)
	at com.sun.tools.attach.VirtualMachine.attach(VirtualMachine.java:250)
	at com.taobao.arthas.core.Arthas.attachAgent(Arthas.java:102)
	at com.taobao.arthas.core.Arthas.<init>(Arthas.java:27)
	at com.taobao.arthas.core.Arthas.main(Arthas.java:161)
[ERROR] attach fail, targetPid: 11490
1
2
3
4
5
6
7
8
9

原因:

Java程序运行用户与arthas运行用户不一致

官网:https://arthas.aliyun.com/

GitHub:https://github.com/alibaba/arthas

上次更新: 2024/11/09, 21:00:16
提升开发效率:JCommander高效Java命令行参数解析利器
高级单元测试中的 Mockito 使用指南

← 提升开发效率:JCommander高效Java命令行参数解析利器 高级单元测试中的 Mockito 使用指南→

最近更新
01
Linux可视化监控
02-26
02
Maven私服搭建
02-26
03
当ElasticSearch时间字段设置多个格式到底是用的哪个?
01-19
更多文章>
Theme by Vdoing | Copyright © 2016-2025 Jast-zsh | MIT License
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式