Arthas 实战指南:从方法耗时定位到 JVM 变量热修改
一、观察方法耗时——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则是进阶利器在紧急修复和性能调优中发挥关键作用。

相关新闻

如何快速批量下载哔咔漫画:多线程下载器完整使用指南

如何快速批量下载哔咔漫画:多线程下载器完整使用指南

如何快速批量下载哔咔漫画:多线程下载器完整使用指南 还在为网络不稳定无法畅快阅读哔咔漫画而烦恼吗?每次追更时突然加载失败,收藏的漫画无法离线保存,手动一页页保存耗时费力……这些问题都将成为过去!今天我要介绍…

2026/10/10 19:12:07 阅读更多 →
本地部署Whisper.cpp+Llama.cpp+ElevenLabs实现GPT-4o级语音交互

本地部署Whisper.cpp+Llama.cpp+ElevenLabs实现GPT-4o级语音交互

1. 项目概述:在本地跑出接近GPT-4o语音交互体验的完整链路“Whisper.cpp Llama.cpp ElevenLabs: Local GPT-4o-like Voice Heaven”——这个标题不是营销噱头,而是我过去三个月反复打磨、压测、拆解再重装的实操成果。它描述的是一条完全脱离云端大模型…

2026/10/3 6:27:07 阅读更多 →
KNN算法实战:从原理到Python实现与优化

KNN算法实战:从原理到Python实现与优化

1. KNN分类器入门:从零开始的机器学习实践 K最近邻(K-Nearest Neighbors,简称KNN)算法是我在数据科学教学中首推的入门算法,原因很简单——它完美诠释了"物以类聚"的直观思想。记得第一次用KNN完成鸢尾花分类…

2026/10/8 3:22:49 阅读更多 →

最新新闻

Java Function接口深度解析:从设计原理到实战应用

Java Function接口深度解析:从设计原理到实战应用

1. 从一个真实场景说起:为什么我们要聊 Function做Java后端的兄弟大概率都遇到过这种代码:一个方法里塞了七八个if-else,每个分支都在做数据转换,参数类型还都不一样。某次需求变更,产品说“这个字段的转换规则要改一下…

2026/10/12 8:45:42 阅读更多 →
“买几送几”应用题解题全解:从折扣本质到分组算法

“买几送几”应用题解题全解:从折扣本质到分组算法

"买几送几"这四个字,估计每个辅导过小学作业的家长都见过。超市酸奶柜贴出"买3送1"时,大多数人第一反应是"等于打了75折",这个直觉没错。可试卷一旦把问题变成"买3件送1件,需要买7件要付几件钱…

2026/10/12 8:45:42 阅读更多 →
GCC 14.2源码构建实战:适配国产系统与C++23编译链

GCC 14.2源码构建实战:适配国产系统与C++23编译链

简介:本资源为GNU Compiler Collection(GCC)官方最新稳定版gcc-14.2.0的完整源码发布包,面向Linux/UNIX系统开发者、编译器研究者、嵌入式工具链构建者及高校计算机系统课程实践者,用于定制化编译器开发、平台移植、性…

2026/10/12 8:45:42 阅读更多 →
火山引擎Agent Toolkit三层架构实战:Plugin、Skills、CLI从零搭建云巡检Agent

火山引擎Agent Toolkit三层架构实战:Plugin、Skills、CLI从零搭建云巡检Agent

1. 从一次云上开发踩坑说起:为什么需要三层架构去年年底我接手了一个云资源自动化巡检的需求,说白了就是每天定时去查一批云主机的状态、磁盘水位、网络配置,发现异常就触发告警和自愈脚本。一开始我想得很简单,写个脚本调API不就…

2026/10/12 8:45:42 阅读更多 →
Java构建生产级AI Agent:解耦决策与执行的工程实践

Java构建生产级AI Agent:解耦决策与执行的工程实践

1. 为什么 Java 还能做 AI Agent?——打破“Java 只适合后端”的思维定式很多人看到“AI Agent”四个字,第一反应是 Python、PyTorch、LangChain、LlamaIndex——这几乎成了行业默认配置。我第一次在某高校实验室看到一个用 Java 写的 Agent 调度器时&am…

2026/10/12 8:45:42 阅读更多 →
gRPC从入门到实战:跨语言微服务通信与Python并发避坑指南

gRPC从入门到实战:跨语言微服务通信与Python并发避坑指南

我真的是太爱学习了——这种念头冒出来的时候,通常不是因为刚学会了一个妙招,而是因为刚被一个不算难的框架折腾到凌晨一点。最近这个对象就是 gRPC。很长一段时间里,我提到 gRPC 都是能躲就躲:要写 .proto、要装 protoc、跨语言还…

2026/10/12 8:44:35 阅读更多 →

日新闻

复古胶片颗粒感噪点合成器:Canvas ImageData 像素高斯杂色注入算法

复古胶片颗粒感噪点合成器:Canvas ImageData 像素高斯杂色注入算法

在数码相机、高清显示屏与现代矢量图形技术高度发达的今天,画面可以做到绝对的锐利、平滑与无瑕。然而,当一张秋日手账插画或拍立得照片过于“平整无瑕”时,往往会散发出一种冰冷生硬的“数码塑料感(Digital Plasticity&#xff0…

2026/10/12 0:00:59 阅读更多 →
活字印刷古籍线装排版:Canvas 竖排文字与栏线自适应算法

活字印刷古籍线装排版:Canvas 竖排文字与栏线自适应算法

在现代网页与移动端设计中,横排(Horizontal Layout)早已经成为了绝对的主流。然而,当我们翻开泛黄的线装古籍、宋版木刻诗集,或是欣赏一张茶道雅集的手写便签时,那种**自上而下纵向书写、自右向左逐列铺展&…

2026/10/12 0:00:59 阅读更多 →
周日晚间的“精神松绑减震器”:无压力情绪倾倒箱与温和轻声陪伴

周日晚间的“精神松绑减震器”:无压力情绪倾倒箱与温和轻声陪伴

每到周日的晚上八点到十点,很多人心里都会悄悄亮起一盏警示灯。 在心理学上,这种现象有一个专门的称谓——“周日夜晚焦虑症(Sunday Scaries)”。明天又是周一,闹钟又要重新在七点响彻卧房;脑海里仿佛有一个…

2026/10/12 0:00:59 阅读更多 →

周新闻

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

简介:基于 ARIMA、LSTM、Transformer 等模型的流感时间序列预测 Python 源码,面向计算机相关专业课程设计与期末大作业学生,以及项目实战学习者。内容覆盖预处理、平稳性检验、定阶、残差分析、多模型对比预测的完整时序建模流程,…

2026/10/12 0:16:30 阅读更多 →
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别 做影刀RPA自动化,十个新手有八个栽在"往输入框里填东西"这件事上:要么填不进去,要么填了一半,要么直接把原来内容追加在后面。这背后的根因&…

2026/10/12 0:16:38 阅读更多 →
影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容 1. 认识影刀:什么场景该用RPA采小说数据 起点中文网的页面结构相对稳定——分类榜单、书籍详情、章节内容三块独立页面,跳转链路清晰。这种场景非常适合影刀自动化&#x…

2026/10/12 0:16:43 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/11 10:45:37 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/11 14:36:53 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/11 14:36:54 阅读更多 →