Arthas安装
1. 在线安装(推荐)
使用官方安装脚本:
# 使用curl curl -O https://arthas.aliyun.com/arthas-boot.jar
# 使用wget wget https://arthas.aliyun.com/arthas-boot.jar启动Arthas:
java -jar arthas-boot.jar2. 包管理器安装
使用Homebrew(macOS):
brew install arthas使用SDKMAN:
sdk install arthas3. 离线安装
下载完整包:
# 从GitHub Releases下载 wget https://github.com/alibaba/arthas/releases/download/arthas-all-3.7.1/arthas-bin.zip unzip arthas-bin.zip cd arthas ./as.sh4. Docker安装
使用Docker运行:
docker run --rm -it hengyunabc/arthas附加到运行中的容器:
docker exec -it <container_name> bash java -jar arthas-boot.jar5. 通过Maven/Gradle依赖安装
Maven项目:
<dependency> <groupId>com.taobao.arthas</groupId> <artifactId>arthas-spring-boot-starter</artifactId> <version>3.7.1</version> </dependency>Gradle项目:
implementation 'com.taobao.arthas:arthas-spring-boot-starter:3.7.1'6. 安装验证
检查版本:
java -jar arthas-boot.jar --version查看帮助:
java -jar arthas-boot.jar -h7. 安装选项参数
指定目标进程:
# 连接到指定PID的进程
java -jar arthas-boot.jar --target-ip 127.0.0.1 --telnet-port 3658 --http-port 8563
# 列出所有Java进程
java -jar arthas-boot.jar --list静默安装:
# 无交互式安装 echo "1" | java -jar arthas-boot.jar8. 安装目录结构
成功安装后,目录结构如下:
arthas/ ├── arthas-boot.jar # 启动器 ├── arthas-core.jar # 核心库 ├── arthas-agent.jar # 代理 ├── as.sh # Linux启动脚本 ├── as.bat # Windows启动脚本 └── lib/ # 依赖库9. 常见安装问题解决
权限问题:
# 添加执行权限 chmod +x as.sh chmod +x arthas-boot.jar网络问题:
# 使用国内镜像
wget https://maven.aliyun.com/repository/public/com/taobao/arthas/arthas-packaging/3.7.1/arthas-packaging-3.7.1-bin.zipJava版本兼容:
- 支持Java 6+
- 推荐Java 8+
10. 卸载方法
清理安装文件:
rm -rf ~/.arthas/ rm -f arthas-boot.jar停止Arthas服务:
# 在Arthas控制台中执行 stop安装建议
- 生产环境:推荐使用离线安装,避免网络依赖
- 开发环境:使用在线安装,方便更新
- 容器环境:使用Docker镜像或挂载方式
- 权限管理:确保有足够的权限附加到目标进程
以上是Arthas的完整安装方法和相关配置说明。
Arthas启动
1. 基础启动命令
启动并选择目标进程:
java -jar arthas-boot.jar启动后会列出所有Java进程,输入数字选择要诊断的进程。
指定PID直接连接:
java -jar arthas-boot.jar [pid]2. 启动参数详解
网络配置:
# 指定IP和端口
java -jar arthas-boot.jar --target-ip 127.0.0.1 --telnet-port 3658 --http-port 8563
# 仅使用HTTP接口(禁用Telnet)
java -jar arthas-boot.jar --telnet-port -1 --http-port 8563会话管理:
# 使用指定会话ID java -jar arthas-boot.jar --session-id my-session
# 设置会话超时时间 java -jar arthas-boot.jar --session-timeout 18003. 高级启动选项
日志配置:
# 指定日志输出级别 java -jar arthas-boot.jar --log-level debug
# 指定日志文件路径 java -jar arthas-boot.jar --log-file /path/to/arthas.log性能调优:
# 设置命令执行超时时间 java -jar arthas-boot.jar --command-timeout 300
# 限制命令执行结果大小 java -jar arthas-boot.jar --result-limit 10485764. 批量操作模式
非交互式启动:
# 通过管道自动选择第一个进程
echo "1" | java -jar arthas-boot.jar
# 执行特定命令后退出
java -jar arthas-boot.jar --batch-command "dashboard -n 1" --pid [pid]脚本执行:
# 执行脚本文件
java -jar arthas-boot.jar --batch-file /path/to/script.txt --pid [pid]5. 连接模式
附加到远程进程:
# 连接远程JVM java -jar arthas-boot.jar --target-ip 192.168.1.100 --pid [pid]隧道连接:
# 通过隧道服务器连接
java -jar arthas-boot.jar --tunnel-server ws://server:8080 --app-name myapp6. 诊断模式
安全模式:
# 只读模式,防止误操作 java -jar arthas-boot.jar --safe-mode统计模式:
# 启用命令执行统计 java -jar arthas-boot.jar --stat-enabled7. 常用组合命令
快速诊断:
# 启动并立即执行dashboard echo -e "1\ndashboard" | java -jar arthas-boot.jar生产环境启动:
java -jar arthas-boot.jar \ --target-ip 127.0.0.1 \ --telnet-port 3658 \ --http-port 8563 \ --log-level info \ --session-timeout 36008. 进程选择技巧
列出所有Java进程:
java -jar arthas-boot.jar --list过滤特定进程:
# 根据进程名过滤 java -jar arthas-boot.jar --select com.example.Application9. 启动问题排查
检查连接状态:
# 验证是否能连接到目标进程 java -jar arthas-boot.jar --test-connection --pid [pid]查看启动帮助:
java -jar arthas-boot.jar --help10. 实际使用示例
开发环境:
# 快速启动,选择第一个进程 java -jar arthas-boot.jar测试环境:
# 指定具体应用进程 ps aux | grep java java -jar arthas-boot.jar [具体的pid]生产环境:
# 完整的生产配置 java -jar arthas-boot.jar \ --pid [生产进程PID] \ --target-ip 127.0.0.1 \ --telnet-port 3658 \ --http-port 8563 \ --log-level warn \ --session-timeout 1800 \ --command-timeout 60这些启动命令覆盖了Arthas的各种使用场景,可以根据具体需求选择合适的启动方式和参数配置。
dashboard命令基本语法
dashboard [选项参数]1. 基本用法
启动仪表板:
dashboard按指定时间间隔刷新:
# 每3秒刷新一次 dashboard -i 3
# 每5秒刷新一次 dashboard -i 5指定刷新次数后退出:
# 刷新10次后自动退出 dashboard -n 102. 输出界面详解
dashboard命令会显示一个实时监控面板,包含多个监控区域:
顶部汇总信息
ID NAME GROUP PRIORITY STATE %CPU TIME INTERRUPTED DAEMON 1 main main 5 RUNNABLE 15.3% 0:05.3 false false 12 http-nio-8080-exec-1 main 5 RUNNABLE 32.1% 1:23.1 true true内存监控区域
Memory used total max usage heap 128M 512M 2G 25% nonheap 45M 64M 256M 17%线程监控区域
Runtime os.name Linux os.version 4.19.0 java.version 1.8.0_291 java.home /usr/lib/jvm/java-8-openjdk systemload.average 0.12 processors 4 uptime 2d 3h 45mGC监控区域
Garbage Collection PS Scavenge count/time 125 / 3.2s PS MarkSweep count/time 8 / 1.5s3. 常用选项参数
-i 设置刷新间隔
# 设置2秒刷新间隔 dashboard -i 2-n 设置刷新次数
# 只刷新5次后退出 dashboard -n 5组合使用
# 每2秒刷新一次,共刷新20次 dashboard -i 2 -n 204. 监控指标说明
CPU使用率
- 显示每个线程的CPU占用百分比
- 可快速定位CPU热点线程
内存使用情况
- heap:堆内存使用情况
- nonheap:非堆内存使用情况
- usage:内存使用率百分比
线程状态
- RUNNABLE:运行中或等待CPU
- BLOCKED:阻塞状态
- WAITING:等待状态
- TIMED_WAITING:限时等待
垃圾收集
- 显示各GC收集器的收集次数和耗时
- 帮助分析GC性能问题
5. 交互操作
刷新控制
- 自动按设定间隔刷新
- 可随时按
q或Ctrl+C退出线程排序
- 默认按CPU使用率排序
- 可查看线程ID、名称、状态等详细信息
6. 实际应用场景
实时性能监控
# 持续监控系统状态 dashboard -i 3问题排查
# 监控一段时间内的系统表现 dashboard -i 2 -n 30内存泄漏分析
通过持续观察内存使用趋势,识别内存泄漏问题
7. 使用技巧
- 快速概览:直接运行
dashboard获取系统整体状态- 持续监控:使用
-i参数设置合适的刷新频率- 自动退出:使用
-n参数避免手动中断- 结合分析:发现异常后使用
thread、jvm等命令深入分析dashboard命令提供了一个全面的实时监控界面,能够帮助开发人员快速了解Java应用的运行状态,识别性能瓶颈和异常情况。
thread命令基本语法
thread [选项参数] [线程ID] [条件表达式]1. 基本用法
查看所有线程:
thread查看指定线程:
thread 1 # 查看线程ID为1的线程
thread 1,2,3 # 查看多个指定线程2. 常用选项参数
-n 显示最忙的线程
# 显示CPU占用率最高的3个线程 thread -n 3-b 检测死锁
# 查找死锁信息 thread -b-i 设置采样间隔
# 每1000毫秒采样一次 thread -i 1000--state 按状态过滤
# 查看RUNNABLE状态的线程 thread --state RUNNABLE
# 查看BLOCKED状态的线程 thread --state BLOCKED
# 查看WAITING状态的线程 thread --state WAITING3. 输出结果详解
标准thread命令输出:
Threads Total: 45, NEW: 0, RUNNABLE: 12, BLOCKED: 2, WAITING: 25, TIMED_WAITING: 6, TERMINATED: 0 ID NAME GROUP PRIORI STATE %CPU TIME INTER DAEMON 1 main main 5 RUNNABL 15.3% 0:05.3 false false 12 http-nio-8080-exec-1 main 5 RUNNABL 32.1% 1:23.1 true true 23 Thread-0 main 5 WAITING 0.0% 0:00.1 false false输出字段说明:
ID:线程IDNAME:线程名称GROUP:线程组PRIORI:优先级STATE:线程状态%CPU:CPU使用率TIME:运行时间INTER:是否中断DAEMON:是否为守护线程thread -n 3 输出:
Threads Total: 45, NEW: 0, RUNNABLE: 12, BLOCKED: 2, WAITING: 25, TIMED_WAITING: 6, TERMINATED: 0 ID NAME STATE %CPU TIME 12 http-nio-8080-exec-1 RUNNABLE 98.5% 5:34.2 13 http-nio-8080-exec-2 RUNNABLE 45.2% 3:12.8 15 pool-1-thread-1 RUNNABLE 12.3% 1:45.6thread -b 死锁检测输出:
Blocked thread: "Thread-1" Id=23 TIMED_WAITING at java.lang.Thread.sleep(Native Method) at com.example.DeadLockDemo.lambda$main$1(DeadLockDemo.java:25) - locked <0x0000000712345678> (a java.lang.Object) at com.example.DeadLockDemo$$Lambda$2/0x0000000800b8e440.run(Unknown Source) at java.lang.Thread.run(Thread.java:748) Blocked thread: "Thread-2" Id=24 BLOCKED at com.example.DeadLockDemo.lambda$main$2(DeadLockDemo.java:35) - waiting to lock <0x0000000712345678> (a java.lang.Object) at com.example.DeadLockDemo$$Lambda$3/0x0000000800b8e840.run(Unknown Source) at java.lang.Thread.run(Thread.java:748) Found 1 deadlock.4. 线程状态说明
- NEW:新建状态,尚未启动
- RUNNABLE:可运行状态,正在执行或等待CPU
- BLOCKED:阻塞状态,等待获取监视器锁
- WAITING:等待状态,无限期等待其他线程操作
- TIMED_WAITING:限时等待状态
- TERMINATED:终止状态
5. 实际应用场景
性能问题排查:
# 找到CPU占用最高的线程 thread -n 3
# 查看该线程的堆栈信息 thread 12死锁检测:
# 快速检测死锁 thread -b线程池监控:
# 监控线程池中线程的状态 thread --state RUNNABLE -n 56. 高级用法
条件表达式过滤:
# 只查看CPU使用率超过50%的线程 thread 'percent > 50'
# 查看特定名称模式的线程 thread 'name ~= "http.*"'持续监控:
# 每2秒采样一次,持续监控 thread -i 20007. 实用技巧
- 快速定位:先用
thread -n 3找到热点线程- 深入分析:再用
thread [线程ID]查看详细堆栈- 状态分析:关注BLOCKED和WAITING状态的线程
- 结合使用:配合
stack命令查看完整调用链路thread命令是排查Java应用性能问题的基础工具,通过分析线程状态和CPU使用情况,可以快速定位死锁、线程阻塞、CPU过高等问题。
monitor命令基本语法
monitor 类全限定名 方法名 [周期] [条件表达式]1. 基本用法
监控单个方法:
# 监控指定方法,默认5秒输出一次统计 monitor com.example.UserService getUserById
# 指定3秒输出一次统计 monitor com.example.UserService getUserById -c 3监控多个方法:
# 监控类中所有方法 monitor com.example.UserService *
# 监控包下所有类的指定方法 monitor com.example.service.* * -c 52. 输出结果详解
monitor命令的典型输出格式:
timestamp | class | method | total | success | fail | avg-ms(rate) 2023-10-01 14:30:00 | com.example.UserService | getUserById | 125 | 120 | 5 | 45.2(96.0%) 2023-10-01 14:30:05 | com.example.UserService | getUserById | 142 | 142 | 0 | 38.7(100.0%) 2023-10-01 14:30:10 | com.example.UserService | getUserById | 118 | 118 | 0 | 42.1(100.0%)输出字段说明:
timestamp:统计时间点class:监控的类名method:监控的方法名total:总调用次数success:成功调用次数fail:失败调用次数avg-ms:平均执行时间(毫秒)rate:成功率百分比3. 常用选项参数
-c 统计周期
# 每2秒统计一次 monitor com.example.UserService getUserById -c 2
# 每10秒统计一次 monitor com.example.UserService getUserById -c 10条件表达式过滤
# 只统计参数大于1000的调用
monitor com.example.UserService getUserById 'params[0] > 1000'
# 只统计执行时间超过50ms的调用
monitor com.example.UserService getUserById '#cost > 50'4. 实际应用场景
性能监控:
# 监控关键业务方法性能
monitor com.example.OrderService createOrder -c 5
monitor com.example.PaymentService processPayment -c 5异常监控:
# 监控方法异常率 monitor com.example.FileService uploadFile -c 10负载监控:
# 监控QPS和响应时间 monitor com.example.ApiController * -c 35. 高级用法
监控构造方法:
# 监控对象创建频率 monitor com.example.UserService <init> -c 5监控静态方法:
# 监控工具类方法 monitor com.example.Utils * -c 10组合监控:
# 同时监控多个服务类 monitor com.example.*Service * -c 56. 输出结果解读示例
假设监控一个用户查询服务:
分析要点:
- 调用量趋势:从156→178→162,相对稳定
- 成功率:96.2%→100%→98.8%,需要关注失败情况
- 性能表现:平均52ms左右,性能稳定
- 异常情况:有少量失败调用,需要进一步排查
7. 实用技巧
- 合理设置周期:根据业务特点设置监控周期,高频方法周期短些
- 关注失败率:fail列不为0时需要注意
- 性能基准:建立方法的性能基准,avg-ms异常时及时排查
- 组合使用:配合watch和trace命令进行深度分析
8. 退出监控
# 按Ctrl+C或Q键退出监控
Press Q or Ctrl+C to abort.monitor命令非常适合用于长期监控方法的性能指标和健康状况,通过周期性的统计输出,可以快速发现性能瓶颈和异常情况。
trace命令基本语法
trace 类全限定名 方法名 [条件表达式] [选项参数]1. 基本用法
追踪单个方法:
# 追踪指定方法的调用链路 trace com.example.UserService getUserById
# 追踪静态方法 trace com.example.Utils formatDate追踪多个方法:
# 追踪类中所有方法 trace com.example.UserService *
# 追踪包下所有类的指定方法 trace com.example.service.* getUser*2. 输出结果详解
trace命令的典型输出格式:
`---ts=2023-10-01 15:30:25;thread_name=http-nio-8080-exec-1;id=23;is_daemon=true;priority=5;TCCL=org.springframework.boot.loader.LaunchedURLClassLoader@123456
`---[12.456ms] com.example.UserService:getUserById()
+---[1.234ms] com.example.UserService:validateInput() #16
+---[8.901ms] com.example.UserMapper:selectById() #17
| `---[8.567ms] org.apache.ibatis.*:execute() #18
`---[2.321ms] com.example.UserService:formatResponse() #19
输出字段说明:
- 显示完整的方法调用链
ts:时间戳thread_name:线程名称id:线程ID#cost:方法执行时间(毫秒)#行号:源代码行号标识3. 常用选项参数
-j 跳过jdk方法
# 跳过JDK内部方法调用,只显示业务代码
trace com.example.UserService getUserById -j-n 执行次数限制
# 只追踪3次调用 trace com.example.UserService getUserById -n 3--skipJDKMethod false 包含JDK方法
# 显示包括JDK方法在内的完整调用链
trace com.example.UserService getUserById --skipJDKMethod false-E 正则表达式匹配
# 使用正则表达式匹配方法名 trace -E com\.example\.service\..* getUser.*4. 条件表达式过滤
基于执行时间:
# 只追踪执行时间超过50ms的调用
trace com.example.UserService getUserById '#cost > 50'基于方法参数:
# 只追踪特定参数的调用
trace com.example.UserService getUserById 'params[0] > 1000'组合条件:
# 组合多个条件
trace com.example.UserService getUserById 'params[0] && #cost > 100'5. 实际应用场景
性能瓶颈定位:
# 追踪慢查询方法 trace com.example.DataService queryLargeData '#cost > 1000'调用链路分析:
# 分析完整业务链路 trace com.example.OrderService createOrder异常调用追踪:
# 追踪特定条件下的调用
trace com.example.PaymentService processPayment 'params[1].amount > 10000'6. 高级用法
追踪构造方法:
# 追踪对象创建过程 trace com.example.UserService <init>追踪接口实现:
# 追踪接口的所有实现方法 trace com.example.*RepositoryImpl *深度追踪:
# 追踪多层调用,显示完整调用树
trace com.example.Controller * --skipJDKMethod false7. 实用技巧
- 精确匹配:使用完整类名和方法名避免误匹配
- 条件过滤:使用条件表达式减少干扰信息
- 结合使用:先使用monitor找到热点方法,再用trace深入分析
- 性能考虑:在生产环境谨慎使用,避免影响应用性能
8. 退出追踪
# 按Ctrl+C或Q键退出追踪
Press Q or Ctrl+C to abort.9. 典型排查流程
# 1. 找到高CPU线程 thread -n 3
# 2. 分析线程堆栈 thread 23
# 3. 追踪热点方法 trace com.example.ExpensiveService calculate
# 4. 分析具体耗时环节 trace com.example.ExpensiveService calculate -jtrace命令是性能分析的重要工具,通过观察方法调用链路和执行时间,可以快速定位性能瓶颈所在的具体代码位置。
watch命令基本语法
watch 类全限定名 方法名 观察表达式 [条件表达式] [选项参数]1. 观察表达式详解
基本观察对象:
# 观察参数 watch com.example.UserService getUserById params
# 观察返回值 watch com.example.UserService getUserById returnObj
# 观察执行时间 watch com.example.UserService getUserById '#cost'
# 观察目标对象 watch com.example.UserService getUserById target
# 观察方法名 watch com.example.UserService getUserById method组合观察表达式:
# 观察多个元素
watch com.example.UserService getUserById '{params, returnObj, #cost}'
# 观察异常信息
watch com.example.UserService getUserById '{params, throwExp, #cost}'
# 观察完整上下文
watch com.example.UserService getUserById '{params, target, returnObj, #cost}'2. 条件表达式过滤
# 只观察执行时间超过100ms的调用
watch com.example.UserService getUserById '{params, returnObj}' '#cost > 100'
# 只观察特定参数的调用
watch com.example.UserService getUserById returnObj 'params[0] > 1000'
# 只观察返回特定结果的调用
watch com.example.UserService getUserById returnObj 'returnObj != null'
# 组合条件
watch com.example.UserService getUserById '{params, #cost}' 'params[0] && #cost > 50'3. 常用选项参数
-x 深度展开
# 展开1层(默认)
watch com.example.UserService getUserById returnObj -x 1
# 展开2层
watch com.example.UserService getUserById returnObj -x 2
# 展开3层(推荐用于复杂对象)
watch com.example.UserService getUserById returnObj -x 3-b 观察方法调用前
# 方法调用前观察参数 watch com.example.UserService getUserById params -b
# 方法调用前观察目标对象状态 watch com.example.UserService getUserById target -b-e 观察方法异常时
# 只在抛出异常时观察
watch com.example.UserService getUserById throwExp -e
# 异常时观察完整上下文
watch com.example.UserService getUserById '{params, throwExp, target}' -e-s 观察方法调用成功后
# 方法成功返回后观察 watch com.example.UserService getUserById returnObj -s-f 观察方法调用结束后
# 方法结束后观察(默认,包含正常返回和异常) watch com.example.UserService getUserById returnObj -f4. 实际应用示例
调试参数传递:
watch com.example.OrderService createOrder params -x 3 -b性能问题排查:
watch com.example.DataService processData '{params, #cost}' '#cost > 500' -s数据一致性问题:
watch com.example.AccountService transfer '{params[0], params[1], target.balance}' -x 2异常排查:
watch com.example.FileService uploadFile '{params, throwExp}' -e5. 高级用法
观察静态方法:
watch com.example.Utils * '{params, returnObj}' -s观察重载方法:
# 观察所有同名方法 watch com.example.Converter convert* '{params, returnObj, #cost}'观察构造方法:
watch com.example.UserService <init> '{params, target}' -b6. 输出结果解读
典型watch输出:
![]()
输出字段说明:
ts:时间戳cost:执行耗时(毫秒)result:观察表达式的结果数组@类型:对象的类型标识输出特点:
- 显示方法调用的详细上下文
- 可以查看参数值(params)
- 可以查看返回值(returnObj)
- 显示执行耗时(#cost)
- 支持深度展开(-x参数控制展开层级)
7. 实用技巧
- 精确匹配方法:使用完整方法签名避免重载方法干扰
- 合理设置深度:-x 2或3通常足够,避免性能问题
- 条件过滤:使用条件表达式减少不必要输出
- 组合使用:配合trace命令进行深度分析
通过灵活运用watch命令的各种选项和表达式,可以深入观察Java方法的执行细节,有效定位各种运行时问题。
Arthas的trace、monitor、watch三个命令都是性能诊断工具三者的主要区别
命令 输出频率 主要用途 数据详细程度 trace 每次调用 分析调用链路 中等 monitor 周期性 统计性能指标 宏观 watch 每次调用 观察具体数据 详细 trace适合分析代码执行路径,monitor适合监控方法性能趋势,watch适合调试具体的数据问题。
stack命令的详细用法
基本语法
stack [option] class-pattern method-pattern [condition-express]常用参数详解
1. 基础用法
# 追踪指定方法的调用路径 stack com.example.UserService getUserById
# 追踪所有public方法 stack com.example.UserService *
# 追踪指定包下的所有方法 stack com.example.service.* *2. 条件过滤参数
# 按调用次数过滤 stack com.example.UserService getUserById '#cost > 100'
# 按参数值过滤 stack com.example.UserService getUserById 'params[0]=="123"'
# 按返回值过滤 stack com.example.UserService getUserById 'returnObj!=null'3. 执行控制参数
# 限制执行次数 stack com.example.UserService getUserById -n 5
# 设置执行时间间隔(毫秒) stack com.example.UserService getUserById -m 1000
# 忽略JDK内部方法 stack com.example.UserService getUserById --skipJDKMethod true4. 输出控制参数
# 显示调用深度 stack com.example.UserService getUserById -d 10
# 限制输出行数 stack com.example.UserService getUserById -l 50
# 按耗时排序 stack com.example.UserService getUserById --orderBy cost实际应用场景
场景1:排查方法调用链路
# 查看某个方法被谁调用 stack com.example.controller.UserController getUserInfo场景2:性能问题定位
# 追踪耗时较长的方法调用 stack com.example.service.* * '#cost > 500'场景3:参数传递追踪
# 追踪特定参数值的调用路径
stack com.example.OrderService createOrder 'params[0].userId == 1001'场景4:异常调用排查
# 追踪返回null的方法调用
stack com.example.DataService queryData 'returnObj == null'高级用法组合
1. 多条件组合
stack com.example.PaymentService processPayment 'params[0].amount > 1000 && #cost > 1000'2. 正则表达式匹配
# 使用正则匹配类名和方法名 stack *Service get* '#cost > 200'3. 线程过滤
# 只追踪指定线程的调用 stack com.example.TaskService execute 'thread.name == "task-thread-1"'输出结果解读
stack命令输出包含:
- 调用栈深度:显示方法调用的层级关系
- 耗时信息:每个调用的执行时间
- 参数值:方法调用的具体参数
- 返回值:方法的返回结果
使用技巧
- 精确匹配:尽量使用完整的类名和方法名
- 条件优化:使用合适的条件表达式减少输出噪音
- 深度控制:根据实际需要调整调用深度
- 性能考虑:避免在生产环境频繁使用高频率追踪
注意事项
- stack命令会显著增加系统开销,生产环境慎用
- 建议先使用sc命令确认类和方法的存在
- 结合watch、trace命令进行综合分析
通过合理使用stack命令,可以快速定位方法调用链路中的问题,提高问题排查效率。
memory命令基本语法
memory命令参数详解
1. 基础内存信息
# 查看内存概览 memory
# 按特定单位显示(默认MB)
memory -k # KB单位
memory -m # MB单位(默认)
memory -g # GB单位2. 堆内存分析
# 查看堆内存详细信息 memory --heap
# 查看堆内存直方图(前10个类) memory --heap -n 10
# 查看堆内存中存活对象 memory --heap --live3. 非堆内存分析
# 查看非堆内存信息 memory --non-heap
# 查看元空间使用情况 memory --metaspace4. 详细内存统计
# 查看内存池详细信息 memory --pools
# 查看垃圾回收器相关信息 memory --gc输出结果解读
memory命令输出包含以下关键信息:
内存区域:
- heap - 堆内存(新生代、老年代)
- non-heap - 非堆内存(方法区、元空间等)
- code cache - JIT编译代码缓存
- metaspace - 元空间(类元数据)
- compressed class space - 压缩类空间
关键指标:
- init - 初始内存大小
- used - 已使用内存大小
- committed - 已提交内存大小
- max - 最大可用内存大小
实际应用场景
场景1:内存泄漏排查
# 定期执行观察内存增长趋势 memory --heap # 间隔一段时间后再次执行对比场景2:OOM问题分析
# 查看各内存区域使用率 memory --pools场景3:内存配置优化
# 查看当前内存配置是否合理 memory高级用法组合
1. 结合其他命令分析
# 先查看内存概况 memory
# 再查看占用内存较多的对象 heapdump --live /tmp/heap.hprof2. 定期监控
# 每5秒执行一次,共执行10次 memory -i 5000 -n 10使用技巧
- 趋势分析:定期执行memory命令观察内存使用趋势
- 对比分析:在操作前后分别执行,对比内存变化
- 综合分析:结合jvm、thread等命令进行综合分析
注意事项
- memory命令不会对系统性能产生显著影响
- 结果中的committed通常大于used,这是正常现象
- 关注used与max的比例,避免接近max值
通过memory命令可以全面了解JVM内存使用情况,为内存优化和问题排查提供重要依据。
jvm命令基本语法
jvm命令功能详解
1. 运行时信息
- JVM名称:HotSpot、OpenJ9等
- Java版本:JDK版本信息
- 启动时间:JVM启动时间戳
- 运行时间:JVM已运行时长
2. 内存相关信息
- 堆内存使用:当前堆内存使用情况
- 非堆内存:方法区、元空间等使用情况
- 垃圾回收器:使用的GC算法和收集器
3. 系统属性
- 操作系统信息:OS名称、架构、版本
- 用户信息:当前用户、工作目录
- 文件编码:默认字符编码
4. 类加载信息
- 已加载类数:当前加载的类数量
- 总加载类数:JVM生命周期内加载的总类数
实际应用场景
场景1:JVM基本信息确认
# 快速查看JVM版本和运行状态 jvm场景2:环境配置检查
# 确认运行环境和配置参数 jvm输出结果解读
jvm命令输出包含以下关键信息:
运行时数据:
- UPTIME - JVM运行时间
- START-TIME - 启动时间
- INPUT-ARGUMENTS - 启动参数
内存相关:
- HEAP-MEMORY-USED - 堆内存已使用量
- NO-HEAP-MEMORY-USED - 非堆内存使用量
线程信息:
- THREAD-COUNT - 活动线程数
- PEAK-THREAD-COUNT - 峰值线程数
使用技巧
- 快速诊断:jvm命令是排查问题的第一步
- 环境确认:用于确认运行环境和配置
- 参数检查:查看JVM启动参数设置
注意事项
- jvm命令执行开销很小,可频繁使用
- 结果中的时间信息基于JVM启动时间
- 关注内存使用率和线程数量变化趋势
通过jvm命令可以快速了解JVM的基本状态,为后续深入诊断提供基础信息。
heapdump命令基本语法
heapdump [--live] [file]参数说明
可选参数
--live:只转存活对象,减少文件大小file:指定输出文件路径,默认为当前目录下的heapdump.hprof文件常用用法示例
1. 生成默认堆转储
# 在当前目录生成heapdump.hprof文件 heapdump2. 指定输出路径
# 生成到指定目录 heapdump /tmp/myheap.hprof3. 只转储存活对象
# 只转储存活对象,文件更小 heapdump --live4. 完整参数组合
# 转储存活对象到指定文件 heapdump --live /tmp/live_heap.hprof文件分析工具
生成的.hprof文件可以使用以下工具分析:
1. Eclipse MAT (Memory Analyzer Tool)
- 功能强大的堆分析工具
- 自动检测内存泄漏
- 提供详细的对象引用链
2. JDK自带的jhat
jhat heapdump.hprof3. VisualVM
- 图形化分析工具
- 直观的对象分布查看
实际应用场景
场景1:内存泄漏分析
# 生成堆转储分析内存泄漏 heapdump /tmp/leak_analysis.hprof场景2:性能优化
# 生成轻量级堆转储,减少对系统影响 heapdump --live /tmp/performance.hprof注意事项
- 文件大小:完整堆转储文件可能很大,注意磁盘空间
- 系统影响:生成堆转储会暂停JVM,生产环境谨慎使用
- 分析时间:大文件分析需要较长时间和足够内存
- 权限:确保有权限写入目标目录
使用技巧
- 在内存使用高峰时生成转储,更容易发现问题
- 使用
--live参数可以减少文件大小和分析时间- 定期生成堆转储进行对比分析
- 结合其他内存监控命令使用效果更好
heapdump命令是诊断内存问题的关键工具,配合分析工具可以深入定位内存泄漏和优化内存使用。
jad命令基本语法
jad [option] [class-name] [method-name]参数说明
主要参数
class-name:要反编译的类名(全限定名)method-name:可选,指定反编译特定方法常用选项
--source-only:只显示源代码,不显示类信息--lineNumber:显示行号信息--code:显示字节码-p:反编译所有方法和属性-c:类加载器的hashcode常用用法示例
1. 反编译整个类
# 反编译指定类 jad com.example.UserService
# 反编译内部类 jad com.example.OuterClass$InnerClass2. 反编译特定方法
# 只反编译指定方法 jad com.example.UserService getUserById
# 反编译重载方法 jad com.example.UserService "getUserById(java.lang.String)"3. 显示源代码(简洁模式)
# 只显示源代码,不显示额外信息 jad --source-only com.example.UserService4. 显示行号信息
# 显示源代码和行号对应关系 jad --lineNumber com.example.UserService5. 显示字节码
# 显示方法的字节码 jad --code com.example.UserService getUserById6. 反编译所有内容
# 反编译类的所有方法和属性 jad -p com.example.UserService7. 指定类加载器
# 当有多个类加载器时指定具体加载器 jad -c 3d4e5f com.example.UserService实际应用场景
场景1:查看线上代码版本
# 确认线上运行的代码版本
jad --source-only com.example.OrderService processOrder场景2:诊断代码问题
# 查看方法实现逻辑,排查问题 jad com.example.PaymentService --lineNumber场景3:学习第三方库
# 查看框架或库的内部实现 jad org.springframework.beans.factory.BeanFactory输出格式说明
jad命令的输出通常包含:
- 类的基本信息(包名、类名)
- 字段定义
- 方法实现(源代码)
- 行号映射信息
使用技巧
- 模糊匹配:可以使用通配符
*进行模糊匹配- 管道配合:可以配合
grep等命令进行过滤- 历史记录:使用
history查看之前反编译的类- 会话保持:在同一个Arthas会话中,可以直接使用类名
注意事项
- jad反编译的是JVM中已加载的类,可能与源码有差异
- 对于匿名内部类,类名会包含数字后缀
- 某些混淆或优化的代码可能反编译结果不理想
- 生产环境使用时要注意性能影响
jad命令是理解代码运行状态、诊断问题的强大工具,特别适用于无法直接查看源码的环境。
jad redefine mc
redefine命令基本语法
redefine /path/to/ClassFile.class
redefine -c <classloader-hash> /path/to/ClassFile.class参数说明
/path/to/ClassFile.class:编译后的class文件路径-c:指定类加载器的hashcode--classLoaderClass:指定类加载器的类名使用前提
- 只能修改方法体,不能添加/删除方法
- 不能修改字段定义
- 不能更改类继承关系
- 新类必须与旧类保持相同的包名和类名
完整使用流程
1. 准备修改的类
// 原始类:UserService.java public class UserService { public String getUserInfo(Long userId) { return "User:" + userId; } } // 修改后类:UserService.java public class UserService { public String getUserInfo(Long userId) { System.out.println("获取用户信息,用户ID:" + userId); return "Modified User:" + userId; } }2. 编译修改后的类
# 编译为class文件 javac UserService.java
# 确认编译成功 ls UserService.class3. 执行redefine命令
# 在Arthas中执行redefine redefine /path/to/UserService.class
# 如果存在多个类加载器,需要指定 redefine -c 3d4e5f /path/to/UserService.class实际应用场景
场景1:紧急修复线上bug
# 1. 定位问题类 jad --source-only com.example.BugService
# 2. 修改源码并编译
# 3. 热更新修复 redefine /tmp/BugService.class
# 4. 验证修复效果 watch com.example.BugService bugMethod场景2:临时添加日志
# 在方法中添加调试日志 redefine /path/to/WithLogs.class场景3:功能开关控制
# 动态启用/禁用某些功能 redefine /path/to/FeatureToggle.class配合其他命令使用
1. 与jad配合
# 先查看当前代码
jad --source-only com.example.TargetClass
# 修改后重新定义 redefine /path/to/TargetClass.class2. 与watch配合验证
# redefine后观察方法执行 watch com.example.TargetClass targetMethod params3. 与sc配合查找类
# 查找类信息 sc -d com.example.TargetClass # 获取类加载器信息用于redefine注意事项
限制条件
- 不能增加方法:新类方法数量必须与旧类一致
- 不能修改方法签名:包括参数、返回类型、方法名
- 不能增删字段:字段结构必须保持一致
- 不能改变继承关系:父类和接口不能改变
风险提示
- 内存泄漏风险:反复redefine可能导致PermGen/Metaspace溢出
- 兼容性问题:修改后的类必须与调用方兼容
- 事务一致性:修改数据库相关代码要注意事务状态
- 回滚准备:准备好回滚方案,防止修改引入新问题
最佳实践
- 测试验证:在测试环境充分验证后再上生产
- 小步修改:每次只修改少量代码,降低风险
- 监控观察:修改后密切监控应用状态
- 及时清理:完成修复后及时部署正式版本
错误处理
常见错误
# 类不匹配错误 redefine error! class: com.example.A not found in classloader # 方法签名不匹配 redefine error! add method: xxx, please check your class file # 解决方案 # - 确认类名完全一致 # - 检查类加载器是否正确 # - 验证修改是否超出限制范围redefine命令是Arthas最强大的功能之一,正确使用可以快速解决线上问题,但需要谨慎操作并充分了解其限制和风险。
mc 命令详细用法
mc [options] [source-files] mc [options] [directory]常用选项
-c, --classloader:指定类加载器的 hashcode-d, --destination:指定编译输出的目录--classLoaderClass:指定类加载器的类名-S, --source:指定源码路径(JDK 9+ 支持模块化时使用)-C, --classpath:指定额外的 classpath完整使用示例
场景1:编译单个Java文件
# 1. 首先使用jad反编译线上类 jad --source-only com.example.UserService > /tmp/UserService.java # 2. 编辑修改源码文件 vim /tmp/UserService.java # 3. 使用mc编译修改后的源码 mc /tmp/UserService.java # 4. 如果编译成功,会显示生成的.class文件路径 Memory compiler output: /tmp/com/example/UserService.class场景2:指定输出目录和类加载器
bashCopy Code
# 指定输出目录和类加载器 mc -d /tmp/classes -c 3d4e5f /tmp/UserService.java
# 编译多个文件 mc -d /tmp/classes /tmp/UserService.java /tmp/OrderService.java场景3:编译整个目录
# 编译目录下的所有java文件 mc /tmp/src/
# 指定类路径编译 mc -C "/home/app/lib/*" /tmp/UserService.javamc + redefine 完整工作流
步骤1:定位并导出问题类
# 查找要修改的类
sc *UserService
# 反编译得到源码
jad --source-only com.example.UserService > /tmp/UserService.java步骤2:修改源码
编辑
/tmp/UserService.java,比如修改方法逻辑:public class UserService { public String getUserInfo(Long userId) { // 添加日志和修改逻辑 System.out.println("[DEBUG] 查询用户信息,ID: " + userId); return "Modified User Info: " + userId; } }步骤3:内存编译
# 编译修改后的源码 mc /tmp/UserService.java # 输出示例: Memory compiler output: /tmp/com/example/UserService.class Affect(row-cnt:1) cost in 320 ms步骤4:热更新类
# 使用redefine加载编译后的类 redefine /tmp/com/example/UserService.class # 输出示例: redefine success, size: 1步骤5:验证修改
# 观察方法执行情况 watch com.example.UserService getUserInfo params输出信息解读
成功编译输出
Memory compiler output: /tmp/com/example/UserService.class Affect(row-cnt:1) cost in 450 ms
- Memory compiler output:编译生成的.class文件路径
- Affect(row-cnt:1):成功编译的文件数量
- cost in 450 ms:编译耗时
编译错误输出
Compilation error: /tmp/UserService.java:15: error: cannot find symbol private NewType newField; ^ symbol: class NewType location: class UserService Affect(row-cnt:0) cost in 280 ms
- 会显示具体的编译错误信息
- row-cnt:0 表示没有文件编译成功
常见问题与解决方案
问题1:编译时找不到符号
原因:缺少依赖类
解决:
# 指定classpath mc -C "/path/to/dependency/*" /tmp/UserService.java问题2:类加载器不匹配
原因:使用了错误的类加载器
解决:
# 先查看类的类加载器 sc -d com.example.UserService # 使用正确的类加载器hash mc -c 3d4e5f /tmp/UserService.java问题3:包结构不一致
原因:源码的包路径与实际类不一致
解决:确保源码文件中的package声明与实际一致注意事项
- 包路径必须一致:源码中的package声明必须与线上类完全一致
- 依赖问题:如果修改的类依赖其他类,需要确保这些类在classpath中可用
- 语法兼容性:使用的Java语法必须与目标JVM版本兼容
- 资源占用:频繁编译可能导致Metaspace内存增长
实际应用场景
紧急bug修复
# 快速修复线上空指针异常
jad --source-only com.example.BugService > /tmp/BugService.java
# 修改源码中的空指针问题
mc /tmp/BugService.java
redefine /tmp/com/example/BugService.class添加调试信息
# 为怀疑有问题的方法添加日志 mc /tmp/WithDebugLogs.java redefine /tmp/com/example/WithDebugLogs.classmc命令大大简化了热更新的流程,避免了手动编译、上传等繁琐步骤,是线上问题紧急修复的重要工具。


8225

被折叠的 条评论
为什么被折叠?



