使用Arthas定位问题
功能概述
首先,Arthas的常用功能大概有以下几个:
- 解决依赖冲突
sc命令:模糊查看当前 JVM 中是否加载了包含关键字的类,以及获取其完全名称。 sc -d 关键字
注意使用 sc -d 命令,获取
classLoaderHash命令:通过 classloader 查看 class 文件来自哪个 jar 包 注意 classloader -c
后面的值填上面获取到的 classLoaderHash值
- 查看线上运行的代码源码,是否是预期的(确认代码是否提交,分支是否正确)
jad --source-only:可以查看源代码。
watch命令:查看方法调用情况。后面跟上完全类名和方法名,以及一个 OGNL的表达式,-f 表示不论正常返回还是异常返回都进行观察,-x 表示输出结果的属性遍历深度,默认为 1,建议无脑写 4就行,最大的遍历深度,再大就不支持了
tt命令:观测方法调用情况,tt命令可以查看「多次调用」并选择其中一个进行观测,但是如果输出结果是多层嵌套就没办法看了,而 watch 可以查看「多层嵌套」的结果。
这两个命令都是用来查看方法调用过程的,不同的是 watch 命令是调用一次打印一次方法的调用情况,而 tt 命令可以先生成一个不断增加的调用列表,然后指定其中某一项进行观测。
- 热启动(类似JRebel)
redefine 命令:「热替换」线上的代码,注意应用重启之后会失效,这在某些紧急情况下会有奇效。
比如说我们修改一下方法体里面的代码,加了一行日志打印
- 看程序运行时的整体情况
dashboard命令:可以查看当前系统的实时数据面板,当运行在Ali-tomcat时,会显示当前tomcat的实时信息,如HTTP请求的qps, rt, 错误数,线程池信息,内存使用情况,系统参数等等。
- 查看程序运行时的jvm状态
jvm 命令:可以查看 JVM 的实时运行状态。
- 定位应用运行中的热点分析系统瓶颈
profiler 命令:支持生成应用热点的火焰图。本质上是通过不断的采样,然后把收集到的采样结果生成火焰图。
应用实例
背景
项目使用了MumbleSDK 2.x, rmb请求先到一个Dispatcher类, 然后Dispatcher根据请求参数里的bizServiceId把请求分发到不同的子服务接口. 各个子服务接口上有个@MumbleMessageService标注着自己对应的bizServiceId.
上个月有个一次性的补数需求, 图方便我就直接在子服务的类里用@Async写了个异步方法, 分发服务Dispatcher就识别不到@MumbleMessageService注解找不到子服务了. 根据组内其他小伙伴的经验, 是因为这个类被spring代理了导致的. 后来把异步方法抽到单独的类实现, 服务就正常了.
但这个bug在测试环境没有复现过, 如果是代理问题,那么在什么环境都应该复现才对, 这篇文章就是寻找测试环境没复现的原因, 以及从源码层面上分析为什么@Async会导致找不到子服务的注解.
本地调试
开发环境运行后bug复现了, 看了Dispatcher分发服务的源码, 原理是系统启动时扫描所有继承了MumbleBaseService的类, 然后遍历实现类以及父类里的方法是否带有@MumbleMessageService, 如果有就放在缓存里, 请求过来时就从缓存里取出对应的服务.
在扫描结束的位置加了断点, 可以看到出问题的那个类由于有个方法用了@Async, 类名带有$Proxy, 是个JDK动态代理类. 而JDK动态代理类和它的父类java.lang.reflect.Proxy 方法上都没有@MumbleMessageService, 所以不会被Dispatcher放进缓存, 子服务自然识别不到了.

那么测试环境的类是什么样的呢?为什么注解能识别到呢? 使用神器Arthas试试.
使用Arthas
1. 首先使用sc命令查看jvm里加载的类信息

发现有个类名带有 $EnhancerBySpringCGLIBEnhancerBySpringCGLIBEnhancerBySpringCGLIB, 是cglib代理类, 而本地调试时类名带有$Proxy, 是JDK代理类, 这个差异很可能就是造成测试环境bug没复现的原因. 而且有好多个在开发环境正常的类测试环境也变成代理类了. 应该是有个地方统一给这些类做了增强. 于是现在问题就变成了 哪里使用了cglib代理了这些类, 而且只在测试环境才使用了呢? 我自己项目里的代码里是没这样用的, 可能是在某个引用的包里. 继续挖.
2. 这次使用trace命令查看方法的调用链, 想看看调用链里有没有发现

输入命令后, 发送一笔请求, 发现只有各个节点的耗时时长, 没有别的信息了. 官方文档这个命令的说明是方法内部调用路径,并输出方法路径上的每个节点上耗时, 看来只能看到方法内部的调用链, 方法外的看不到, 而我要找的是哪里增强了这个方法.
3. 接下去尝试使用stack命令查询方法被调用的调用路径
下图是发送请求后stack命令打印出来的东西, 出现了一个mumbleSDK里的类, 名字看起来就是使用了AOP切面

找到这个类源码, 就是它了! MumbleSDK里的dao,rmb调用耗时监控组件, 给项目里service目录下的类都做了cglib代理, 而且只有测试环境满足了@Conditional里的条件所以开启了.

让我们验证下, 在项目的配置文件里加上 mumble.monitor.web.enabled=false 关闭这个监控服务. 部署到测试环境后bug终于重现了. 再次使用sc查看, 之前的cglib代理类已经变成JDK代理了

4. 用jad命令反编译两种不同的代理类
下图是cglib的, 可以看到继承的父类是原来的类. 再复习下MumbleSDK Dispatcher识别服务的原理: 遍历实现类以及父类的方法扫描@MumbleMessageService注解. 所以可以识别到方法上的@MumbleMessageService并把子服务加进缓存. 这就是一开始测试环境能识别到子服务的原因.

下图是jdk代理类, 父类是Proxy, 方法上没有@MumbleMessageService. 也就会出现找不到子服务的问题了.

所以这个bug的根本原因是不同类型的动态代理的实现差异导致的, 而不是一开始认为的单纯是因为被代理了.
下图是@EnableAsync里的代码, 默认是jdk代理.

回到本地开发环境, 把@EnableAsync改成 @EnableAsync(proxyTargetClass = true), 强制使用cglib代理. 重启服务, 开发环境的服务也正常了.
但是, 为了能乱放@Async而去改spring的默认代理配置是不合理的, 还是要把@Async方法独立出去.
Arthas Idea插件
命令或类名太长记不得可以安装使用Aethas的idea插件,如下图,在方法上右键选中相应的命令, 就可以把命令复制到剪贴板, 直接去终端粘贴使用就行了. 比如下图粘贴的结果是 stack cn.webank.pmbank.cp.ocr.service.impl.OcrCorePojoService DoCommonOcr -n 5

总结
- 以前只了解过两种动态代理的实现机制及区别, 没感受过这种区别对系统运行造成的影响. 就这个bug来说, 是代理类的父类不同造成的.
以后如果遇到这类问题也多了个debug思路. - Arthas真香. 以前debug时用的笨方法都可以用它代替. 比如定位接口耗时长问题, 不用在代码里一段段打印耗时日志再重新部署了,
一行trace命令就可以打印出各个链路的耗时; 比如不确定部署的代码是不是刚才更新的, 可以使用jad反编译查看变更的类. - 带有@Async @Schedule @Transation 等注解的方法最好分类放到单独的类里, 比如专门的异步任务类, 定时任务类等.不仅能避免代理方面的问题, 也能使代码结构更清晰整洁.
相关文章:
使用Arthas定位问题
功能概述 首先,Arthas的常用功能大概有以下几个: 解决依赖冲突 sc命令:模糊查看当前 JVM 中是否加载了包含关键字的类,以及获取其完全名称。 sc -d 关键字 注意使用 sc -d 命令,获取 classLoaderHash命令:…...
性能测试之tomcat+nginx负载均衡
nginx tomcat 配置准备工作:两个tomcat 执行命令 cp -r apache-tomcat-8.5.56 apache-tomcat-8.5.56_2修改被复制的tomcat2下conf的server.xml 的端口号,不能与tomcat1的端口号重复,不然会启动报错 ,一台电脑上想要启动多个tomcat,…...
【手写 Vuex 源码】第十一篇 - Vuex 插件的开发
一,前言 上一篇,主要介绍了 Vuex-namespaced 命名空间的实现,主要涉及以下几个点: 命名空间的介绍和使用;命名空间的逻辑分析与代码实现;命名空间核心流程梳理; 本篇,继续介绍 Vu…...
opencv基础知识和绘图图形
大家好,我是csdn的博主:lqj_本人 这是我的个人博客主页: lqj_本人的博客_CSDN博客-微信小程序,前端,python领域博主lqj_本人擅长微信小程序,前端,python,等方面的知识https://blog.csdn.net/lbcyllqj?spm1011.2415.3001.5343哔哩哔哩欢迎关注…...
15- 决策回归树, 随机森林, 极限森林 (决策树优化) (算法)
1. 决策回归树: from sklearn.tree import DecisionTreeRegressor model DecisionTreeRegressor(criterionmse,max_depth3) model.fit(X,y) # X是40个点 y是一个圆 2. 随机森林 稳定预测: from sklearn.ensemble import RandomForestClassifier # model RandomForestC…...
Flink相关的记录
Flink源码编译首次编译的时候,去除不必要的操作,同时install会把Flink中的module安装到本地仓库,这样依赖当前module的其他组件就无需去远程仓库拉取当前module,节省了时间。mvn clean install -T 4 -DskipTests -Dfast -Dmaven.c…...
配置可视化-基于form-render的无代码配置服务(一)
背景 有些业务场景需要产品或运营去配置JSON数据提供给开发去使用(后面有实际业务场景的说明),原有的业务流程,非开发人员(后面直接以产品指代)把数据交给开发,再由开发去更新JSON数据。对于产…...
Java 代理模式详解
1、代理模式 代理模式是一种比较好理解的设计模式。简单来说就是 我们使用代理对象来代替对真实对象(real object)的访问,这样就可以在不修改原目标对象的前提下,提供额外的功能操作,扩展目标对象的功能。 代理模式的主要作用是扩展目标对象…...
知识付费小程序怎么做_分享知识付费小程序的作用
在线知识付费产业的主要业务逻辑是基于用户的主动学习需求,为其提供以跨领域基础知识与技能为核心的在线知识服务,提升其达到求知目的的效率。公众号和小程序的迅速发展,又为知识付费提供了技术支持,从而促进了行业的进一步发展。…...
14- 决策树算法 (有监督学习) (算法)
决策树是属于有监督机器学习的一种决策树算法实操: from sklearn.tree import DecisionTreeClassifier # 决策树算法 model DecisionTreeClassifier(criterionentropy,max_depthd) model.fit(X_train,y_train)1、决策树概述 决策树是属于有监督机器学习的一种,起源…...
如何编译和运行C++程序?
C 和C语言类似,也要经过编译和链接后才能运行。在《C语言编译器》专题中我们讲到了 VS、Dev C、VC 6.0、Code::Blocks、C-Free、GCC、Xcode 等常见 IDE 或编译器,它们除了可以运行C语言程序,还可以运行 C 程序,步骤是一样的&#…...
Golang 给视频添加背景音乐 | Golang工具
目录 前言 环境依赖 代码 总结 前言 本文提供给视频添加背景音乐,一如既往的实用主义。 主要也是学习一下golang使用ffmpeg工具的方式。 环境依赖 ffmpeg环境安装,可以参考我的另一篇文章:windows ffmpeg安装部署_阿良的博客-CSDN博客 …...
让AI护理医疗:解决卫生系统的痛点
一、引言 1.对医疗领域中AI技术的介绍 随着人工智能的不断发展,它已经成为了各个领域中的重要组成部分。在医疗领域中,AI技术也逐渐发挥着越来越重要的作用。从诊断到治疗,从健康管理到研究,人工智能已经深刻地影响着医疗领域的…...
Windows 离线安装 MySQL 8
目录 1. 下载离线安装包 2. 上传解压 3 配置 my.ini 文件 4 设置系统环境变量 5 安装 MySQL 6 登录 MySQL 客户环境是内网环境,不能访问外网,只能离线安装 MySQL 了。 1. 下载离线安装包 MySQL 离线压缩包官网下载地址:MySQL :: Down…...
【前端攻城狮之vue基础】02路由+嵌套路由+路由query/params传参+路由props配置+replace属性+编程式路由导航+缓存路由组件
路由的基础知识1.路由简介2.路由基本使用3.嵌套路由4.传递路由的query传参# 5.传递路由的params参数6.路由的props传参配置7.路由router-link标签的replace属性8.编程式路由导航9.缓存路由组件1.路由简介 路由是一条条对应的key-value关系,key就是前端地址栏的路径…...
CHAPTER 1 Zabbix介绍及安装
Zabbix介绍及安装1.1 Zabbix监控1 为什么要监控1.1 网站可用性2 监控什么东西2.1 监控范畴3 怎么来监控3.1 远程管理服务器3.2 监控硬件3.3 查看cpu相关3.4 内存3.5 磁盘3.6 监控网络4 监控工具总览5 zabbix介绍5.1 zabbix的组成5.2 zabbix监控范畴1.2 安装zabbix1 环境检查2 安…...
认识V模型、W模型、H模型
软件测试与软件工程息息相关,软件测试是软件工程组成中不可或缺的一部分。 在软件工程、项目管理、质量管理得到规范化应用的企业,软件测试也会进行得比较顺利,软件测试发挥的价值也会更大。 要关注软件工程、质量管理以及配置管理与软件测试…...
excel ttest检测
1、excel函数含义 TTEST(array1,array2,tails,type) ▪ Array1: 第一组数据集 ▪ Array2: 第二组数据集 ▪ Tails: 用于定义所返回的分布的尾数: 1 代表单尾;2 代表双尾 ▪ Type: 用于定义 t-检验的类型: 1 代表成对检验;2 代表双样本等方差假设&am…...
PDFPrinting.Net操作进行细粒度控制
PDFPrinting.Net操作进行细粒度控制 PDFPrinting.Net能够容易且灵活地预测完美的打印结果以及用户文件的示例性显示。可以快速浏览.NET PDF打印中最关键的元素。如果用户需要获得更详细的概述,那么他可以查看快速入门手册,甚至是现有文档的详细概述参考。…...
SegPGD
在这项工作中,我们提出了一种有效和高效的分割攻击方法,称为SegPGD。此外,我们还提供了收敛性分析,表明在相同次数的攻击迭代下,所提出的SegPGD可以创建比PGD更有效的对抗示例。此外,我们建议应用我们的Seg…...
Linux应用开发之网络套接字编程(实例篇)
服务端与客户端单连接 服务端代码 #include <sys/socket.h> #include <sys/types.h> #include <netinet/in.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <arpa/inet.h> #include <pthread.h> …...
DeepSeek 赋能智慧能源:微电网优化调度的智能革新路径
目录 一、智慧能源微电网优化调度概述1.1 智慧能源微电网概念1.2 优化调度的重要性1.3 目前面临的挑战 二、DeepSeek 技术探秘2.1 DeepSeek 技术原理2.2 DeepSeek 独特优势2.3 DeepSeek 在 AI 领域地位 三、DeepSeek 在微电网优化调度中的应用剖析3.1 数据处理与分析3.2 预测与…...
Java 8 Stream API 入门到实践详解
一、告别 for 循环! 传统痛点: Java 8 之前,集合操作离不开冗长的 for 循环和匿名类。例如,过滤列表中的偶数: List<Integer> list Arrays.asList(1, 2, 3, 4, 5); List<Integer> evens new ArrayList…...
Admin.Net中的消息通信SignalR解释
定义集线器接口 IOnlineUserHub public interface IOnlineUserHub {/// 在线用户列表Task OnlineUserList(OnlineUserList context);/// 强制下线Task ForceOffline(object context);/// 发布站内消息Task PublicNotice(SysNotice context);/// 接收消息Task ReceiveMessage(…...
【位运算】消失的两个数字(hard)
消失的两个数字(hard) 题⽬描述:解法(位运算):Java 算法代码:更简便代码 题⽬链接:⾯试题 17.19. 消失的两个数字 题⽬描述: 给定⼀个数组,包含从 1 到 N 所有…...
[ICLR 2022]How Much Can CLIP Benefit Vision-and-Language Tasks?
论文网址:pdf 英文是纯手打的!论文原文的summarizing and paraphrasing。可能会出现难以避免的拼写错误和语法错误,若有发现欢迎评论指正!文章偏向于笔记,谨慎食用 目录 1. 心得 2. 论文逐段精读 2.1. Abstract 2…...
【Java_EE】Spring MVC
目录 Spring Web MVC 编辑注解 RestController RequestMapping RequestParam RequestParam RequestBody PathVariable RequestPart 参数传递 注意事项 编辑参数重命名 RequestParam 编辑编辑传递集合 RequestParam 传递JSON数据 编辑RequestBody …...
MySQL 8.0 OCP 英文题库解析(十三)
Oracle 为庆祝 MySQL 30 周年,截止到 2025.07.31 之前。所有人均可以免费考取原价245美元的MySQL OCP 认证。 从今天开始,将英文题库免费公布出来,并进行解析,帮助大家在一个月之内轻松通过OCP认证。 本期公布试题111~120 试题1…...
爬虫基础学习day2
# 爬虫设计领域 工商:企查查、天眼查短视频:抖音、快手、西瓜 ---> 飞瓜电商:京东、淘宝、聚美优品、亚马逊 ---> 分析店铺经营决策标题、排名航空:抓取所有航空公司价格 ---> 去哪儿自媒体:采集自媒体数据进…...
【HTTP三个基础问题】
面试官您好!HTTP是超文本传输协议,是互联网上客户端和服务器之间传输超文本数据(比如文字、图片、音频、视频等)的核心协议,当前互联网应用最广泛的版本是HTTP1.1,它基于经典的C/S模型,也就是客…...
