Arthas - Java诊断与调试的瑞士军刀(一)
一、故事的开端,从一个诡异的bug开始
笔者负责了FICC量化金工的项目——情景分析(下文简称为:项目A),其引用了一个公共库fane-lib-java (下文简称为:lib B),内部包含了四个子module。
由于lib B里面防御性编程的缺失,当某个参数异常的传入了null, 导致lib B抛出了NullPointerException, 从而导致项目A计算失败。
根据报错信息,问题定位到了com.huatai.quant.models.scenario.QuantScenarioDefModel类。根据笔者在项目中的搜索结果,下意识的定位在了lib B里的fane-core module
NPE本身的处理并不复杂,在lib B 的fane core module里加入大量参数校验即可避免。但是紧接着出现了“诡异”的现象:
lib B修复NPE后,本地Windows调试正常。 但部署到sit Linux服务器上,依然抛出NPE
常规解决方案尝试
笔者逐个尝试了以下可能的解决方法,均无法解决:
- 检查代码,确认cherrypick到指定分支 —— 排除了代码未check in的低级错误
- 重新build代码并部署 —— 排除build的不是最新代码
- 解压缩sit服务器上,lib B里fane-core的jar包,确认修改的代码进入了fane-core.jar包 —— 排除了sit 服务器使用的是旧代码
在“已确认代码修改进入了jar”后,代码修改依旧不生效, 让笔者百思不得其解...
二、故事的中段,嗅到bug的方向
尝试多种常规解决方法后,NPE异常依然存在,说明此bug非常的不常规...
并不再是代码层面导致的,而是“操作系统”、“硬件机器”等非代码因素造成的。
非常规解决方案尝试
笔者再次尝试了做了以下操作:
- 在同事的本地windows机器上运行,一切正常 —— 再次排除代码的问题
- 尝试部署到另一台sit Linux服务器,依然不工作 —— 此时已经嗅到了bug的方向
通过上述两个操作可以察觉,异常bug的造成,极有可能和操作系统的不同有关联。
三、故事的转折,瑞士军刀Arthas登场
尽管bug的可能原因,已经定位到了Windows和Linux的系统差异。但是由于不方便在Linux服务器上进行debug, 因此需要一种在线监测java运行时状态的监测工具的协助。
经过调研,笔者选择了Arthas —— 这是一款阿里开发的诊断工具,可以用于监视、分析和解决 Java 应用程序的问题。使用 Arthas 的一个主要优点是,我们不需要修改代码,甚至不需要重新启动我们想要监视的 Java 服务。(关于Arthas详细的入门和使用,详见本文第四节)
jad命令 -- 在线反编译已加载类源码
Arthas有一个“jad”命令,可以在线反编译已加载类源码。笔者带着尝试的心情,想再次确认运行时加载的是否是最新代码。没想到输出结果的Location信息,令人错愕...
结果显示,加载的com.huatai.quant.models.scenario.QuantScenarioDefModel类并非来预想的自fane-core.jar,而是来自fane-data-sdk-plus.jar...
经过检查,fane-data-sdk-plus module里,的确也存在着一个相同全类名路径的相同类名的class,甚至内部的内容也一致。导致该bug的根本原因,就此真相大白。
至于当时为何如此设计(或者这是一个被忽略的bug),目前已“失落无考”。不过这验证了我们之前的推测,windows和linux系统,在面对两个相同的类时,存在一个默认的但不同的加载优先级,导致出如此诡异的现象。
四、故事的结尾,简要介绍Arthas的入门和使用
Arthas的安装
离线安装
先在本地,通过镜像地址,下载zip包:
https://arthas.aliyun.com/download/latest_version?mirror=aliyun
然后把下载好的zip包上传至服务器某文件夹,解压zip包(unzip xxx-jar)即可
在线安装
如果服务器所处环境可以连接外网,那么可以使用curl来在线下载并安装 Arthas 库:
curl -O https://alibaba.github.io/arthas/arthas-boot.jar
Arthas的启动
先进入arthas的安装目录,然后执行:
java -jar arthas-boot.jar
如果arthas启动成功,将会看到arthas罗列出的java程序列表:
- [1]: 23748 com.huatai.quant.PortRiskServiceApplication
- [2]: 15781 com.huatai.quant.ScenarioServiceApplication
- [3]: 22537 com.huatai.nats.xxljob.quant.XxljobQuantApplication
- [4]: 1418 com.huatai.quant.KPIServiceApplication
输入你想跟踪的java进程编号。例如你想跟踪ScenarioServiceApplication,那就输入2,然后回车,arthas就会attach到ScenarioServiceApplication
Arthas的命令分类
arthas的命令有许多,大致分为三类:
- JVM相关命令
- 监控类命令
- classloader相关的命令
本文已经提及的 jad命令 属于监控类命令,笔者将在下一篇文章中,分享其他命令的使用心得和踩坑记录。
敬请期待,还望多多指教。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?
2021-02-23 SpringCloud - Eureka vs ZooKeeper
2021-02-23 SpringCloud - Eureka Server 的数据同步过程?
2021-02-23 SpringCloud - 分布式系统的数据同步方式