一、观察方法耗时——trace / stack1.1 命令说明命令用途前提trace追踪方法调用链及每一层耗时有流量经过实例stack输出方法被调用的调用路径有流量经过实例1.2 实战案例接口慢在哪里千阶智能外呼系统接口出现响应超时第一步就是用trace逐层定位耗时瓶颈# 追踪 WordQueryAPIImpl.getWord 的调用链耗时 trace com.qianjie.smart.api.word.WordQueryAPIImpl getWord输出结果会以树状结构展示每一层调用的耗时一目了然地看到哪个子方法是”罪魁祸首”---[123.45ms] com.qianjie.smart.api.word.WordQueryAPIImpl:getWord() ---[2.31ms] com.qianjie.smart.api.word.WordQueryAPIImpl:validateParam() #45 ---[5.67ms] com.qianjie.smart.api.word.WordQueryAPIImpl:preProcess() #52 ---[110.23ms] com.qianjie.smart.api.word.WordQueryAPIImpl:doResponse() #68 ---[1.12ms] com.qianjie.smart.api.word.WordQueryAPIImpl:postProcess() #75从输出可以看到doResponse耗时 110ms是整个接口的瓶颈。假设发现doResponse中主要是transform2RespWithFilter在耗时则继续深入# 继续追踪下一层 trace com.qianjie.smart.factory.ModelFactoryImpl transform2RespWithFilter ---[105.89ms] com.qianjie.smart.factory.ModelFactoryImpl:transform2RespWithFilter() ---[0.45ms] com.qianjie.smart.factory.ModelFactoryImpl:getFilterList() #120 ---[98.76ms] com.qianjie.smart.filter.WordFilterChain:doFilter() #135 | ---[50.12ms] com.qianjie.smart.filter.WordMatchFilter:doFilter() #45 | ---[45.67ms] com.qianjie.smart.filter.WordRankFilter:doFilter() #78 ---[3.21ms] com.qianjie.smart.factory.ModelFactoryImpl:buildResponse() #150可以看到WordFilterChain:doFilter耗时 98ms其中WordMatchFilter和WordRankFilter分别消耗了 50ms 和 45ms这就是根因所在。排障思路像剥洋葱一样从入口方法开始逐层trace直到定位到真正的耗时节点。1.3 进阶用法# 过滤耗时大于 100ms 的调用 trace com.example.Service method #cost 100 # 排除 jdk 内部调用路径 trace com.example.Service method --exclude-class-pattern java.* # 追踪多次调用默认只追踪一次 trace com.example.Service method -n 5二、观察方法入参、返回值——watch2.1 命令说明watch是 Arthas 中最灵活的命令之一可以观察方法的入参params、返回值returnObj、异常throwExp以及目标对象target。观察点参数说明方法调用前-b观察入参方法返回后默认观察返回值方法异常后-e观察异常同时观察-b -s -e全生命周期2.2 实战案例连接池配置是否生效问题背景千阶智能平台配置了连接池最大值为 200但疑似未生效。配置文件如下spring: datasource: hikari: maximum-pool-size: 200通过 Arthas 验证实际生效值# 只查看最大连接数 watch com.zaxxer.hikari.HikariConfig getMaximumPoolSize Affect(class count: 1, method count: 1) cost in 45 ms, listenerId: 1 methodcom.zaxxer.hikari.HikariConfig.getMaximumPoolSize locationAtExit ts2026-07-13 10:23:45; resultInteger[10] # 查看所有属性展开2层 watch com.zaxxer.hikari.HikariConfig getMaximumPoolSize -x 2 Affect(class count: 1, method count: 1) cost in 38 ms, listenerId: 2 methodcom.zaxxer.hikari.HikariConfig.getMaximumPoolSize locationAtExit ts2026-07-13 10:24:12; resultInteger[10] HikariConfig[ maximumPoolSizeInteger[10], minimumIdleInteger[10], idleTimeoutLong[600000], maxLifetimeLong[1800000], connectionTimeoutLong[30000], ... ]结果分析配置最大连接数为 200实际生效为 10 →不符合预期配置未生效配置最大连接数为 5实际生效为 5 →符合预期关键洞察watch让我们在不重启、不加日志的情况下直接”看到”运行时的变量值快速验证配置是否按预期加载。2.3 进阶用法# 观察入参和返回值 watch com.example.Service method {params, returnObj} -x 3 # 按条件过滤只观察第一个参数大于 100 的调用 watch com.example.Service method {params, returnObj} params[0] 100 # 观察异常 watch com.example.Service method {params, throwExp} -e # 观察调用耗时 watch com.example.Service method #cost三、获取与修改 JVM 变量——ognl这是 Arthas 最强大的能力之一在运行时读取甚至修改 JVM 内部的任意变量无需重启服务。3.1 静态变量# 获取静态变量 ognl com.example.ConfigDEFAULT_VALUE # 修改静态变量 ognl com.example.ConfigDEFAULT_VALUEnew_value3.2 实例变量场景获取方式修改方式有流量通过watchwatch ognl 表达式无流量通过springbean ognlspringbean ognl3.3 实战案例无流量时修改实例变量千阶智能平台在凌晨无流量时段需要紧急修改某个业务服务的实例变量。第一步准备 BeanFactoryHelper在项目中新增一个静态 Bean 工厂类通过 Spring 的BeanFactoryAware回调获取BeanFactoryComponent public class BeanFactoryHelper implements BeanFactoryAware { private static BeanFactory beanFactory; Override public void setBeanFactory(BeanFactory beanFactory) throws BeansException { BeanFactoryHelper.beanFactory beanFactory; } public static Object getBean(String beanName) { return beanFactory.getBean(beanName); } public static T T getBean(ClassT requiredType) { return beanFactory.getBean(requiredType); } public static boolean containsBean(String beanName) { return beanFactory.containsBean(beanName); } }第二步获取目标类的 ClassLoader Hashsc -df com.qianjie.smart.infrastructure.bs.BsQueryService输出中重点关注classLoaderHash后续 ognl 命令需要用到class-info com.qianjie.smart.infrastructure.bs.BsQueryService code-source file:/home/work/java/smart-app/target/smart-app.jar!/BOOT-INF/lib/smart-infrastructure-1.0.0.jar!/ name com.qianjie.smart.infrastructure.bs.BsQueryService isInterface false isAnnotation false isEnum false isAnonymousClass false isArray false isLocalClass false isMemberClass false isPrimitive false isSynthetic false simple-name BsQueryService modifier public annotation org.springframework.stereotype.Component interfaces super-class -java.lang.Object class-loader -org.springframework.boot.loader.LaunchedURLClassLoader6767c1fc -jdk.internal.loader.ClassLoaders$AppClassLoader2f333739 -jdk.internal.loader.ClassLoaders$PlatformClassLoader1172f803 classLoaderHash 6767c1fc fields name log type org.slf4j.Logger modifier final,private,static value Logger[com.qianjie.smart.infrastructure.bs.BsQueryService] name protocolSeparator type java.lang.String modifier name enter type java.lang.String modifier name defaultKey type java.lang.String modifier第三步查看变量ognl -c 6767c1fc #instancecom.qianjie.smart.utils.BeanFactoryHelpergetBean(bsQueryService)输出BsQueryService[ logLogger[Logger[com.qianjie.smart.infrastructure.bs.BsQueryService]], protocolSeparatorString[\r\n.\r\n], enterString[\r\n], defaultKeyString[99], ]第四步修改变量ognl -c 6767c1fc #instancecom.qianjie.smart.utils.BeanFactoryHelpergetBean(bsQueryService), #fieldObjcom.qianjie.smart.infrastructure.bs.BsQueryServiceclass.getDeclaredField(defaultKey), #fieldObj.setAccessible(true), #fieldObj.set(#instance,88)修改后再次观察确认defaultKey已从99变为88BsQueryService[ ... defaultKeyString[88], ]核心原理通过 Spring BeanFactory 获取实例引用再通过反射setAccessible(true)突破 访问控制直接修改 私有字段值。整个过程无需重启 JVM。四、类加载与热替换 Class当线上代码有 Bug 但无法立即发版时Arthas 支持热替换 Class 文件# 查看类加载信息 sc -df com.example.TargetClass # 反编译线上代码确认当前逻辑 jad com.example.TargetClass methodName # 热替换用本地编译好的 class 文件替换线上的 redefine /path/to/TargetClass.class注意事项redefine后原来的类不能被 GC需注意内存影响优先使用retransform它支持回滚操作热替换是临时方案务必在下一版本中正式修复五、CPU 与内存热点分析5.1 CPU 线程热点# 查看最消耗 CPU 的线程 thread -n 5 # 查看指定线程的堆栈 thread thread-id # 查找死锁 thread -b5.2 CPU 方法热点# 持续采样输出最耗 CPU 的方法 profiler start --event cpu # ... 运行一段时间 ... profiler stop5.3 内存方法热点# 分析内存分配热点 profiler start --event alloc # ... 运行一段时间 ... profiler stop建议 profiler 采样时间建议 30s-60s太短数据不准太长影响性能。六、经典排障案例总结Case 1接口太慢定位耗时根因trace 入口方法 → 发现慢子方法 → trace 子方法 → 逐层深入 → 定位根因关键像剥洋葱一样逐层追踪不要一次 trace 太深。Case 2变量值是否符合预期场景命令有流量经过watch 观察入参/返回值无流量经过springbean ognl 直接读取Case 3配置中心丢失需紧急修改配置场景千阶智能配置中心挂了不能重启一重启就挂但需要修改某个 VIP 地址或域名。方案一Arthas 热修改# 通过 springbean ognl 直接修改 JVM 内部的配置变量 ognl -c classLoaderHash #instancecom.example.BeanFactoryHelpergetBean(configBean), #fieldcom.example.ConfigBeanclass.getDeclaredField(targetVip), #field.setAccessible(true), #field.set(#instance,10.10.10.10)方案二内核四层转发需 root 权限# 配置 iptables 将旧 VIP 的流量转发到新 VIP iptables -t nat -A PREROUTING -d 10.11.12.13 -j DNAT --to-destination 10.10.10.10方案选择优先用 Arthas 热修改影响范围小只有在 Arthas 无法触达的场景才用 iptables。七、Arthas 命令速查表场景命令说明方法耗时trace 类名 方法名逐层追踪调用链耗时调用路径stack 类名 方法名查看方法被谁调用入参/返回值watch 类名 方法名 {params,returnObj}观察方法入参和返回值静态变量ognl 类名变量名读取/修改静态变量实例变量ognl springbean读取/修改实例变量类信息sc -df 类名查看类加载信息反编译jad 类名 方法名查看线上代码热替换redefine /path/to/Class.class热替换 Class 文件CPU 热点线程thread -n 5Top 5 CPU 消耗线程死锁检测thread -b查找死锁性能采样profiler start/stopCPU/内存热点分析结语Arthas 的核心价值在于不重启、不侵入、实时诊断。掌握trace、watch、ognl三板斧足以应对 80% 的线上排障场景。而redefine和profiler则是进阶利器在紧急修复和性能调优中发挥关键作用。