简介
Arthas 官网地址(https://arthas.aliyun.com/en-us/) Arthas Github (https://github.com/alibaba/arthas)
谢谢阿里有提供一个这么好用的调试工具,记得很久以前写Asp.Net 的时候未了线上调试,用到花生壳转发映射到本地或者直接在服务器安装VS调试等
基础命令
cat
打印文件内容,和linux里的cat命令类似。
cat [文件路径]
cls
清空当前屏幕区域
echo
打印参数,和linux里的echo命令类似。
echo [参数]
base64
base64编码转换,和linux里的 base64 命令类似。
# 对文本内容base64编码
base64 /tmp/test.txt
# 对文本内容base64编码后输出
base64 --input /tmp/test.txt --output /tmp/result.txt
# 对文本文件解码
base64 -d /tmp/result.txt
# 用 base64 解码文件并保存结果到文件里
base64 -d /tmp/result.txt --output /tmp/bbb.txt
tee
类似传统的tee命令, 用于读取标准输入的数据,并将其内容输出成文件。
tee [文件路径]
# 将会把输入的内容输出到文件
pwd
返回当前的工作目录,和linux命令类似
pwd
reset
重置增强类,将被 Arthas 增强过的类全部还原,Arthas 服务端stop时会重置所有增强过的类
# 还原指定类
trace Test test
# 还原所有类
trace
version
输出当前目标 Java 进程所加载的 Arthas 版本号
history
打印命令历史
quit
退出当前 Arthas 客户端,其他 Arthas 客户端不受影响
stop
关闭 Arthas 服务端,所有 Arthas 客户端全部退出
身份认证
auth
session
高级命令
dashboard
线程参数
- 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
- 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线程
# 线程预览
thread
# 查看指定线程 输出线程堆栈信息
thread [线程ID]
# 查看阻塞的线程
thread -b
# 指定cpu使用率统计的采样间隔,单位为毫秒,默认值为200
thread -i [毫秒数]
# 显示全部线程
thread --all
# 查看指定状态的线程
thread –state [WAITING|RUNNABLE|TIMED_WAI]
jvm
输出JVM 信息
重要参数说明
THREAD相关
- COUNT: JVM当前活跃的线程数
- DAEMON-COUNT: JVM当前活跃的守护线程数
- PEAK-COUNT: 从JVM启动开始曾经活着的最大线程数
- STARTED-COUNT: 从JVM启动开始总共启动过的线程次数
-
文件描述符相关
MAX-FILE-DESCRIPTOR-COUNT:JVM进程最大可以打开的文件描述符数
- OPEN-FILE-DESCRIPTOR-COUNT:JVM当前打开的文件描述符数
查询参数
# 搜索属性
jvm | grep [关键词]
sysprop
查看(修改)当前JVM的系统属性
SystemProperty
# 查看全部系统属性
sysprop
# 查看单个系统属性
sysprop [属性名称]
# 例
sysprop user.country
# 修改系统属性
sysprop [属性名称] [属性值]
# 例
sysprop user.country [修改值]
sysenv
查看当前JVM的环境属性
SystemEnvironmentVariables
# 查看当前环境变量
sysenv
vmoption
perfcounter
logger
查看logger信息,更新Logger Level
mbean
sc
“Search-Class” 的简写,这个命令能搜索出所有已经加载到 JVM 中的 Class 信息,这个命令支持的参数有 [d]、[E]、[f] 和 [x:]。
# 模糊搜索
sc com.*
# 打印类的详细信息, Tab 会有智能提示
sc -d [包]
# 打印类的详细信息 以及字段
sc -d -f [包]
# 打印类的详细信息 以及字段的深度
sc [包] -d -f -x [深度]
sm
“Search-Method” 的简写,这个命令能搜索出所有已经加载了 Class 信息的方法信息。
# 输出类方法信息
sm [包]
# 输出类方法详细信息
sm -d [包]
dump
dump 已加载类的 bytecode 到特定目录
# 将类的class 输出
dump [类路径] [输出路径(选填)]
# 例
dump java.lang.String [-d [路径]]
heapdump
dump java heap, 类似jmap命令的heap dump功能
# dump到指定文件
heapdump /tmp/dump.hprof
# dump live对象
heapdump --live /tmp/dump.hpro
# 默认输出
heapdump
vmtool
vmtool 利用JVMTI接口,实现查询内存对象,强制GC等功能。
指定 classloader name
# --limit参数,可以限制返回值数量,避免获取超大数据时对JVM造成压力。默认值是10
vmtool --action getInstances --className java.lang.String --limit 10
指定 classloader hash
# 查看hash
sc -d org.springframework.context.ApplicationContext
# vmtool -c [HASH]
# 例
vmtool --action getInstances -c 19469ea2 --className org.springframework.context.ApplicationContext
指定返回结果展开层数
# vmtool -x [层数]
# 例
vmtool --action getInstances -c 19469ea2 --className org.springframework.context.ApplicationContext -x 2
执行表达式
vmtool --action getInstances --classLoaderClass org.springframework.boot.loader.LaunchedURLClassLoader --className org.springframework.context.ApplicationContext --express 'instances[0].getBeanDefinitionNames()'
强制GC
vmtool --action forceGc
jad
反编译指定已加载类的源码
# 查看源代码
jad [类路径]
# 例 包含ClassLoader
jad java.lang.String
# 仅输出源代码不包含ClassLoader
jad com.xxscloud.mes.Application --source-only
# 反编译方法
jad com.xxscloud.mes.Application main --source-only
# 反编译时不显示行号
jad com.xxscloud.mes.Application --source-only --lineNumber false
classloader
查看classloader的继承树,urls,类加载信息
基础用法
# 基本信息
classloader
# 查看统计信息
classloader -l
# 查看继承树
classloader -t
查看URLClassLoader实际的urls
classloader -c [HASH]
使用ClassLoader去查找resource
classloader -c [HASH] -r [资源路径]
使用ClassLoader去加载类
classloader -c [Hash] --load [类路径]
# 例
classloader -c 3d4eac69 --load demo.MathGame
monitor
watch
trace
tt
回顾问题
- 这个类从哪个 jar 包加载的?为什么会报各种类相关的 Exception?
- 我改的代码为什么没有执行到?难道是我没 commit?分支搞错了?
- 遇到问题无法在线上 debug,难道只能通过加日志再重新发布吗?
- 线上遇到某个用户的数据处理有问题,但线上同样无法 debug,线下无法重现!
- 是否有一个全局视角来查看系统的运行状况? 有什么办法可以监控到JVM的实时运行状态?
- 怎么快速定位应用的热点,生成火焰图?
- 怎样直接从JVM内查找某个类的实例?