简介

Arthas 官网地址(https://arthas.aliyun.com/en-us/) Arthas Github (https://github.com/alibaba/arthas

谢谢阿里有提供一个这么好用的调试工具,记得很久以前写Asp.Net 的时候未了线上调试,用到花生壳转发映射到本地或者直接在服务器安装VS调试等

基础命令

cat

打印文件内容,和linux里的cat命令类似。

  1. cat [文件路径]

cls

清空当前屏幕区域

echo

打印参数,和linux里的echo命令类似。

  1. echo [参数]

base64

base64编码转换,和linux里的 base64 命令类似。

  1. # 对文本内容base64编码
  2. base64 /tmp/test.txt
  3. # 对文本内容base64编码后输出
  4. base64 --input /tmp/test.txt --output /tmp/result.txt
  5. # 对文本文件解码
  6. base64 -d /tmp/result.txt
  7. # 用 base64 解码文件并保存结果到文件里
  8. base64 -d /tmp/result.txt --output /tmp/bbb.txt

tee

类似传统的tee命令, 用于读取标准输入的数据,并将其内容输出成文件。

  1. tee [文件路径]
  2. # 将会把输入的内容输出到文件

pwd

返回当前的工作目录,和linux命令类似

  1. pwd

reset

重置增强类,将被 Arthas 增强过的类全部还原,Arthas 服务端stop时会重置所有增强过的类

  1. # 还原指定类
  2. trace Test test
  3. # 还原所有类
  4. trace

version

输出当前目标 Java 进程所加载的 Arthas 版本号

history

打印命令历史

quit

退出当前 Arthas 客户端,其他 Arthas 客户端不受影响

stop

关闭 Arthas 服务端,所有 Arthas 客户端全部退出

身份认证

auth

session

高级命令

dashboard

image.png

线程参数

  • ID: Java级别的线程ID,注意这个ID不能跟jstack中的nativeID一一对应。
  • NAME: 线程名
  • GROUP: 线程组名
  • PRIORITY: 线程优先级, 1~10之间的数字,越大表示优先级越高
  • STATE: 线程的状态
  • CPU%: 线程的cpu使用率。比如采样间隔1000ms,某个线程的增量cpu时间为100ms,则cpu使用率=100/1000=10%
  • DELTA_TIME: 上次采样之后线程运行增量CPU时间,数据格式为秒
  • TIME: 线程运行总CPU时间,数据格式为分:秒
  • INTERRUPTED: 线程当前的中断位状态
  • DAEMON: 是否是daemon线程

JVM 内部线程

Java 8之后支持获取JVM内部线程CPU时间,这些线程只有名称和CPU时间,没有ID及状态等信息(显示ID为-1)。 通过内部线程可以观测到JVM活动,如GC、JIT编译等占用CPU情况,方便了解JVM整体运行状况。

  • 当JVM 堆(heap)/元数据(metaspace)空间不足或OOM时,可以看到GC线程的CPU占用率明显高于其他的线程。
  • 当执行trace/watch/tt/redefine等命令后,可以看到JIT线程活动变得更频繁。因为JVM热更新class字节码时清除了此class相关的JIT编译结果,需要重新编译。

thread

image.png

  • ID: 线程ID
  • NAME: 线程名称
  • GROUP: 线程分组
  • PRIORITY: 线程优先级, 1~10之间的数字,越大表示优先级越高
  • STATE: 线程的状态
  • CPU%: 线程的cpu使用率。比如采样间隔1000ms,某个线程的增量cpu时间为100ms,则cpu使用率=100/1000=10%
  • DELTA_TIME: 上次采样之后线程运行增量CPU时间,数据格式为秒
  • TIME: 线程运行总CPU时间,数据格式为分:秒
  • INTERRUPTED: 线程当前的中断位状态
  • DAEMON: 是否是daemon线程
  1. # 线程预览
  2. thread
  3. # 查看指定线程 输出线程堆栈信息
  4. thread [线程ID]
  5. # 查看阻塞的线程
  6. thread -b
  7. # 指定cpu使用率统计的采样间隔,单位为毫秒,默认值为200
  8. thread -i [毫秒数]
  9. # 显示全部线程
  10. thread --all
  11. # 查看指定状态的线程
  12. thread state [WAITING|RUNNABLE|TIMED_WAI]

jvm

输出JVM 信息

image.png

重要参数说明

THREAD相关

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

    文件描述符相关

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

  • OPEN-FILE-DESCRIPTOR-COUNT:JVM当前打开的文件描述符数

查询参数

  1. # 搜索属性
  2. jvm | grep [关键词]

sysprop

查看(修改)当前JVM的系统属性 SystemProperty

image.png

  1. # 查看全部系统属性
  2. sysprop
  3. # 查看单个系统属性
  4. sysprop [属性名称]
  5. # 例
  6. sysprop user.country
  7. # 修改系统属性
  8. sysprop [属性名称] [属性值]
  9. # 例
  10. sysprop user.country [修改值]

sysenv

查看当前JVM的环境属性 SystemEnvironmentVariables

  1. # 查看当前环境变量
  2. sysenv

vmoption

perfcounter

logger

查看logger信息,更新Logger Level

mbean

sc

“Search-Class” 的简写,这个命令能搜索出所有已经加载到 JVM 中的 Class 信息,这个命令支持的参数有 [d]、[E]、[f] 和 [x:]。

image.png

  1. # 模糊搜索
  2. sc com.*
  3. # 打印类的详细信息, Tab 会有智能提示
  4. sc -d [包]
  5. # 打印类的详细信息 以及字段
  6. sc -d -f [包]
  7. # 打印类的详细信息 以及字段的深度
  8. sc [包] -d -f -x [深度]

sm

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

image.png

  1. # 输出类方法信息
  2. sm [包]
  3. # 输出类方法详细信息
  4. sm -d [包]

dump

dump 已加载类的 bytecode 到特定目录

image.png

  1. # 将类的class 输出
  2. dump [类路径] [输出路径(选填)]
  3. # 例
  4. dump java.lang.String [-d [路径]]

heapdump

dump java heap, 类似jmap命令的heap dump功能

  1. # dump到指定文件
  2. heapdump /tmp/dump.hprof
  3. # dump live对象
  4. heapdump --live /tmp/dump.hpro
  5. # 默认输出
  6. heapdump

vmtool

vmtool 利用JVMTI接口,实现查询内存对象,强制GC等功能。

指定 classloader name

  1. # --limit参数,可以限制返回值数量,避免获取超大数据时对JVM造成压力。默认值是10
  2. vmtool --action getInstances --className java.lang.String --limit 10

指定 classloader hash

  1. # 查看hash
  2. sc -d org.springframework.context.ApplicationContext
  3. # vmtool -c [HASH]
  4. # 例
  5. vmtool --action getInstances -c 19469ea2 --className org.springframework.context.ApplicationContext

指定返回结果展开层数

  1. # vmtool -x [层数]
  2. # 例
  3. vmtool --action getInstances -c 19469ea2 --className org.springframework.context.ApplicationContext -x 2

执行表达式

  1. vmtool --action getInstances --classLoaderClass org.springframework.boot.loader.LaunchedURLClassLoader --className org.springframework.context.ApplicationContext --express 'instances[0].getBeanDefinitionNames()'

强制GC

  1. vmtool --action forceGc

jad

反编译指定已加载类的源码

image.png

  1. # 查看源代码
  2. jad [类路径]
  3. # 例 包含ClassLoader
  4. jad java.lang.String
  5. # 仅输出源代码不包含ClassLoader
  6. jad com.xxscloud.mes.Application --source-only
  7. # 反编译方法
  8. jad com.xxscloud.mes.Application main --source-only
  9. # 反编译时不显示行号
  10. jad com.xxscloud.mes.Application --source-only --lineNumber false

classloader

查看classloader的继承树,urls,类加载信息

基础用法

  1. # 基本信息
  2. classloader
  3. # 查看统计信息
  4. classloader -l
  5. # 查看继承树
  6. classloader -t

查看URLClassLoader实际的urls

  1. classloader -c [HASH]

使用ClassLoader去查找resource

  1. classloader -c [HASH] -r [资源路径]

使用ClassLoader去加载类

  1. classloader -c [Hash] --load [类路径]
  2. # 例
  3. classloader -c 3d4eac69 --load demo.MathGame

monitor

watch

trace

tt


回顾问题

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