当前位置: 首页 > news >正文

Arthas使用指北——命令、原理及案例

1 整合方式

当前普遍使用容器化的部署方式,两种方式部署到tke容器中

  • docker打包时将arthas打包进去
  • 在容器中下载
curl -O https://alibaba.github.io/arthas/arthas-boot.jar

boot包仅有一百多 KB

执行

java -jar arthas.jar

即可进入arthas命令行,选择正在执行的java进程后,即可对进程进行相应的在线检测、诊断与调试。

2 实现原理

2.1 Java Agent和Instrumentation

我们知道,IDE中的Debug是通过JDPA技术实现了对代码的远程调试控制。而生产环境中是不会提供给我们JDPA接口的,Arthas使用的是Java Agent技术。

Java Agent 又叫做 Java 探针,Java Agent 是在 JDK1.5 引入的,是一种可以动态修改 Java 字节码的技术。Java 类编译之后形成字节码被 JVM 执行,在 JVM 在执行这些字节码之前获取这些字节码信息,并且通过字节码转换器对这些字节码进行修改,来完成一些额外的功能,这种就是 Java Agent 技术。在许多文章中,Java Agent被描述为虚拟机级别的AOP

实际上单说Java Agent的话,并不涉及字节码的修改,Java Agent是运行在main方法之前的拦截器,它内定的方法名叫 premain ,也就是说要先执行premain再执行main方法。也就是说,Java Agent仅仅是作为代理,为我们提供了在main函数运行之前的一个入口。

public static void premain(String agentArgs, Instrumentation inst); 
public static void premain(String agentArgs);

Java Agent是一个概念,其具体的实现是借助于java.lang.instrument包。在JDK1.5中,Instrument 要求在运行前利用命令行参数或者系统参数来设置代理类,在实际的运行之中,虚拟机在初始化之时(在绝大多数的 Java 类库被载入之前), instrumentation 的设置已经启动,并在虚拟机中设置了回调函数,检测特定类的加载情况,并完成实际工作。但是在实际的很多的情况下,我们没有办法在虚拟机启动之时就为其设定代理,这样实际上限制了 instrument 的应用。而 Java SE 6 的新特性改变了这种情况,通过 Java Tool API 中的 attach 方式,通过VirtualMachine.attachVirtualMachine.loadAgent把agent attach到pid上,我们可以很方便地在运行过程中动态地设置加载代理类,以达到 instrumentation 的目的。而在运行时加载agent,就不再实现premain,而是实现agentmain这个方法。

public static void agentmain(String agentArgs, Instrumentation inst); 
public static void agentmain(String agentArgs);

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ED3jyFvy-1662182362358)(https://km.woa.com/files/photos/pictures/202108/1630248252_2_w1082_h508.jpg)]
整个流程如上图所示,总共可分为如下六步。

  1. 在 JVM 启动时,通过 JVM 参数 -javaagent,传入 agent jar,Instrument Agent 被加载;
  2. 在 Instrument Agent 初始化时,注册了 JVMTI 初始化函数 eventHandlerVMinit
  3. 在 JVM 启动时,会调用初始化函数 eventHandlerVMinit,启动了 Instrument Agent,用 sun.instrument.instrumentationImpl类里的方法loadClassAndCallPremain 方法去初始化 Premain-Class 指定类的 premain 方法;
  4. 初始化函数 eventHandlerVMinit,注册了 class 解析的 ClassFileLoadHook 函数;
  5. 在解析 Class 之前,JVM 调用 JVMTIClassFileLoadHook 函数,钩子函数调用 sun.instrument.instrumentationImpl 类里的 transform 方法,通过TransformerManagertransformer 方法最终调用我们自定义的 Transformer 类的 transform 方法(在premainagentmain中指定);
  6. 因为字节码在解析 Class 之前改的,直接使用修改后的字节码的数据流替代,最后进入 Class 解析,对整个 Class 解析无影响;

对于我们通过attach的方式进行instrumentation,则是对class文件进行重新加载,走5、6两个步骤。

2.2 JVMTI

在2.1节中介绍了JVMTI,JVMTI全称JVM Tool Interface,是JVM暴露出来的一些供用户扩展的接口集合,JVMTI是基于事件驱动的,也就是JVM每执行到一定的逻辑时就会调用一些事件的回调接口(如果回调接口存在),这些接口就可以被开发者扩展自己的逻辑。JVMTIAgent 是一个利用 JVMTI 暴露出来的接口提供了代理启动时加载(agent on load)、代理通过attach形式加载(agent on attach)和代理卸载(agent on unload)功能的动态库。而 instrument agent 可以理解为一类 JVMTIAgent 动态库,别名是 JPLISAgent(Java Programming Language Instrumentation Services Agent) ,也就是 专门为java语言编写的插桩服务提供支持的代理
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-wPNKFPhi-1662182362359)(https://km.woa.com/files/photos/pictures/202108/1630251937_41_w1166_h688.png)]

2.3 ASM

另一个扮演了重要角色的工具就是我们经常使用的ASM,Java字节码操纵框架。Java class 被存储在严格格式定义的 .class 文件里,这些类文件拥有足够的元数据来解析类中的所有元素:类名称、方法、属性以及 Java 字节码(指令)。ASM 从类文件中读入信息后,能够改变类行为,分析类信息,甚至能够根据用户要求生成新类。在许多Java项目中都能看到ASM的身影,比如CGLIB动态代理和lombok的@Data注解自动生成getter和setter。

在2.1节对字节码文件进行修改时,就是通过ASM直接修改class文件,以实现java程序的动态修改,如打印日志等。

3 常用命令

3.1 基础命令

help——查看命令帮助信息

cls——清空当前屏幕区域

reset——重置增强类,将被 Arthas 增强过的类全部还原,Arthas 服务端关闭时会重置所有增强过的类

quit——退出当前 Arthas 客户端,其他 Arthas 客户端不受影响

stop——关闭 Arthas 服务端,所有 Arthas 客户端全部退出

3.2 jvm相关

dashboard——当前系统的实时数据面板,包含线程及内存信息

thread——查看当前 JVM 的线程堆栈信息

jvm——查看当前 JVM 的信息

ognl——执行ognl表达式

heapdump——dump java heap, 类似jmap命令的heap dump功能

3.3 class/classloader相关

sc——search class查看JVM已加载的类信息

sm——search method查看已加载类的方法信息

jad——反编译指定已加载类的源码

mc——内存编译器,内存编译.java文件为.class文件

retransform——加载外部的.class文件,retransform到JVM里

classloader——查看classloader的继承树,urls,类加载信息,使用classloader去getResource

3.4 monitor/watch/trace相关

此类命令,都通过字节码增强技术来实现的,会在指定类的方法中插入一些切面来实现数据统计和观测,线上使用时需谨慎,尽量明确需要观测的类、方法以及条件,诊断结束要执行stop或将增强过的类执行 reset 命令。

4 优秀实践

Alibaba Arthas实践–获取到Spring Context,然后为所欲为 · Issue #482 · alibaba/arthas (github.com)

工商银行打造在线诊断平台的探索与实践

5 参考资料

官方文档

GitHub源码

Arthas运行原理 - 知乎 (zhihu.com)

Arthas在JAVA程序问题排查中的应用 - 质变 - KM平台 (woa.com)

深入理解Instrument(一) - 云+社区 - 腾讯云 (tencent.com)

相关文章:

  • 简历撰写——Java与.NET(当年毕业生版本)
  • zookeeper知识点扫盲
  • UE5学习笔记 判断物体是否在相机视野内
  • 移动安全实战分享
  • Springboot操作mongodb的两种方法:MongoTemplate和MongoRepository
  • 流畅的Python读书笔记-第九章-符合Python风格的对象
  • S0011基于51单片机DS18B20温控风扇仿真设计
  • express演示前端解决跨域的方法jsonp、cors
  • SCA Sentinel 分布式系统的流量防控(二)
  • 姿态分析开源工具箱MMPose安装及使用示例(2d face landmark detection)
  • Java8中anyMatch()、allMatch()、noneMatch()用法详解
  • 【SpringMVC】SpringMVC实现转发和重定向
  • 离散化模板
  • 一种加权变异的粒子群算法-附代码
  • 带符号整数的除法与余数
  • css的样式优先级
  • js正则,这点儿就够用了
  • laravel with 查询列表限制条数
  • React组件设计模式(一)
  • session共享问题解决方案
  • SpiderData 2019年2月23日 DApp数据排行榜
  • 半理解系列--Promise的进化史
  • 聚簇索引和非聚簇索引
  • 使用docker-compose进行多节点部署
  • 吐槽Javascript系列二:数组中的splice和slice方法
  • 学习笔记TF060:图像语音结合,看图说话
  • 再谈express与koa的对比
  • (pojstep1.3.1)1017(构造法模拟)
  • (ZT)一个美国文科博士的YardLife
  • (搬运以学习)flask 上下文的实现
  • (附源码)springboot 个人网页的网站 毕业设计031623
  • (接口封装)
  • (免费领源码)Java#Springboot#mysql农产品销售管理系统47627-计算机毕业设计项目选题推荐
  • (强烈推荐)移动端音视频从零到上手(下)
  • (转)linux 命令大全
  • (轉貼) 資訊相關科系畢業的學生,未來會是什麼樣子?(Misc)
  • *上位机的定义
  • .NET CORE 3.1 集成JWT鉴权和授权2
  • .net 反编译_.net反编译的相关问题
  • .net 流——流的类型体系简单介绍
  • .NET6 开发一个检查某些状态持续多长时间的类
  • .net项目IIS、VS 附加进程调试
  • []Telit UC864E 拨号上网
  • [1204 寻找子串位置] 解题报告
  • [20171106]配置客户端连接注意.txt
  • [8-27]正则表达式、扩展表达式以及相关实战
  • [C/C++]关于C++11中的std::move和std::forward
  • [C/C++随笔] char与unsigned char区别
  • [C++]模板与STL简介
  • [CDOJ 838]母仪天下 【线段树手速练习 15分钟内敲完算合格】
  • [CSS] - 修正IE6不支持position:fixed的bug
  • [HOW TO]怎么在iPhone程序中实现可多选可搜索按字母排序的联系人选择器
  • [LeeCode]-Divide Two Integers 不用乘除的除法运算
  • [leetcode] Multiply Strings
  • [Linux]文件基础-如何管理文件