从利用Arthas排查线上Fastjson问题到Java动态字节码技术(中)

本文从Arthas源码出发,探讨Java Agent技术,它是JVM的一个后门,常用于动态编译、热部署、APM监控等。Arthas使用Java Agent attach JVM并load agent,通过`pre-main`和`agent-main`实现静态与动态Agent。核心是通过Instrument对原字节码增强,实现功能动态织入。文章详述了Arthas的启动流程,包括加载关键类、执行初始化操作以及利用Netty搭建的server。下篇将继续深入讲解Arthas如何运用instrument实现字节码级别的功能织入。
摘要由CSDN通过智能技术生成

上一篇文章 中通过对一次线上事故的复盘,引出了福报厂的Arthas,一个建立在Java动态字节码技术之上的Java诊断工具;关于Arthas的使用方式就不赘述了,查看官方文档可以很快上手,玩法也特别多;上一篇中也仅仅只介绍了一种使用场景,即”debug线上JVM内部class信息、在线watch方法执行并查看方法输入输出、在线反编译class、重新编辑Java后直接热部署“的组合拳(手动狗头)…

上手一门技术最基本要做到 what-how-why,在知道了Arthas是什么(what),以及如何使用(how)之后,自然需要去了解它内如如何工作的,以及底层原理(why);而了解底层原理最直接的方式便是阅读源码,毕竟代码不会骗人的,但任何技术文章或书籍都会有”噪音“,那么接下来就从Arthas源码入手,聊聊Java Agent、Instrument、动态字节码技术;

一直都回避写源码方向的文章,源码读起来容易,但写解读就需要粘贴大量代码,会占据大量篇幅,并且很容易写成流水账,但像Arthas或者Dubbo这类优秀的国产项目还是值得的;
同时由于时间与精力有限,本篇着重介绍Java Agent,Instrument等动态字节码技术放到下一篇…


Arthas源码

记得当初第一次拿到Arthas源码的时候,印象最深的就是那可爱的TODO.md,哈哈,像是某位福娃老哥在做交接…

* 代码还是很乱,需要继续重构
* 依赖需要清理,几个问题:
    * 所有 apache 的 common 库应当不需要
    * json 库有好几份
    * `jopt-simple` 看下能不能用 `cli` 取代
    * `cli`, `termd` 的 artifactId, version 需要想下。是不是应该直接拿进来。他们的依赖也需要仔细看一下
* termd 依赖 netty,感觉有点重,而且第一次 attach 比较慢,不确定是 netty 的问题还是 attach 的问题
* 目前 web console 依赖 termd 中自带的 term.js 和 css,需要美化,需要想下如何集成到研发门户上
* 因为现在没有 Java 客户端了,所以 batch mode 也就没有了
* `com.taobao.arthas.core.shell.session.Session` 的能力需要和以前的 session 的实现对标。其中:
    * 真的需要 textmode 吗?我觉得这个应该是 option 的事情
    * 真的需要 encoding 吗?我觉得仍然应该在 option 中定义,就算是真的需要,因为我觉得就应该是 UTF-8
    * duration 是应当展示的,session 的列表也许也应当展示
    * 需要仔细看下 session 过期是否符合预期
    * 多人协作的时候 session 原来是在多人之间共享的吗?
* 所有的命令现在实现的是 AnnotatedCommand,需要继续增强的是:
    * Help 中的格式化输出被删除。需要为 `@Description` 定义一套统一的格式
    * 命令的输入以及输出的日志 (record logger) 被删除,需要重新实现,因为现在是用 `CommandProcess` 来输出,所以,需要在 `CommandProcess` 的实现里打日志
* `com.taobao.arthas.core.GlobalOptions` 看上去好奇怪,感觉是 OptionCommand 应当做的事情
* `com.taobao.arthas.core.config.Configure` 需要清理,尤其是和 http 相关的
* 需要合并 develop 分支上后续的修复
* 代码中的 TODO/FIXME

回归主题,首先直奔 arthas-core 模块,因为这是整个arthas的入口,即执行java -jar arthas-core.jar;主函数内最重要的任务就是通过java进程的pid来 attach JVM 与 load agent;

private void attachAgent(Configure configure) throws Exception {
   
    VirtualMachineDescriptor virtualMachineDescriptor = null;
    for (VirtualMachineDescriptor descriptor : VirtualMachine.list()) {
   
        String pid = descriptor.id();
        if (pid.equals(Long.toString(configure.getJavaPid()))) {
   
            virtualMachineDescriptor = descriptor;
            break;
        }
    }
    VirtualMachine virtualMachine = null;
    try {
   
        if (null == virtualMachineDescriptor) {
    // 使用 attach(String pid) 这种方式
            virtualMachine = VirtualMachine.attach("" + configure.getJavaPid());
        } else {
   
            virtualMachine = VirtualMachine.attach(virtualMachineDescriptor);
        }
        //略
        virtualMachine.loadAgent(arthasAgentPath, configure.getArthasCore() + ";" 
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值