Alibaba OneJavaAgent 初探

本文探讨了OneJava-Agent的插件模式,包括plugin.properties引导、plugin-jar与instrument-lib的作用,以及如何与传统agent和ByteKit/ByteBuddy字节码处理工具的对比。重点介绍了在AOP代理中ByteBuddy的优雅设计与ByteKit的字节码直接修改的差异。

一、使用

1、plugin

在这种模式下,one-java-agent在加载plugin时,会从以下几个方面进行,分别是

描述
plugin.properties 这个文件是一个引导文件,里面的配置内容引导plugin加载
plugin-jar plugin的引导包,内有实现PluginActivator,用于引导和管理plugin的初始化和销毁
instrument-lib 这个目录存放plugin的代理逻辑和Instrument类

在项目中有demo,以dubbo-test-plugin为例,在${oneagent.home}路径下新建目录,例如dubbo,该目录的内容如下:
在这里插入图片描述

plugin.properties文件内容如下:
在这里插入图片描述

在运行dubbo应用时添加相应的启动参数:

java -javaagent:${oneagent.home}/one-java-agent.jar=oneagent.home=${oneagent.home} org.apache.dubbo.springboot.demo.provider.ProviderApplication

如果是在idea则是在run/debug configurations 添加运行配置:
在这里插入图片描述

Dubbo consumer应用也是一样的,运行发起调用后,会输出instrument-jar中添加的增强逻辑。
在dubbo-test-plugin中是对org.apache.dubbo.rpc.Invoker 接口的实现类在invoke()方法中都添加日志,内容如下:
在这里插入图片描述

2、agent

one-java-agent 对于原生agent jar的支持也是非常简单直接的,在插件目录下面放一个plugin.properties,并且放上原生的agent jar文件。

plugin.properties配置内容例如:

type=traditional
name=demo-agent
version=1.0.0
agentJarPath=demo-agent.jar

则 one java agent会启动这个demo-agent。

二、设计

One java agent的代码量并不多,设计也非常巧妙,模块示意图如下:
在这里插入图片描述

one-java-agent的引导就是Bootstrap,会先初始化三个component,分别管理classloader, class share, 和class file transformer, 然后再从oneagent.home目录加载plugin的信息,找到PluginActivator,逐个激活plugin,在这个过程中会找到plugin中的instrument信息(增强类),创建InstrumentTransformer,然后就交由Java的Instrumentation完成后面的转换逻辑。
这里提一下,InstrumentTransformer中关于字节码的处理是通过alibaba-bytekit实现的。

三、alibaba-bytekit与bytebuddy

ByteKit和byte-buddy都是基于ASM提供更高层的字节码处理能力, 两者都提供丰富的注入点支持。

1、两者比较

ByteKit是阿里开源的字节码处理插件,在其开源的介绍内容中有对比byte-buddy。

功能 函数Enter/Exit注入点 绑定数据 inline 防止重复增强 避免装箱/拆箱开销 origin调用替换 @ExceptionHandler
ByteKit @AtEnter
@AtExit
@AtExceptionExit
@AtFieldAccess
@AtInvoke
@AtInvokeException
@AtLine
@AtSyncEnter
@AtSyncExit
@AtThrow
this/args/return/throw
field
locals
子调用入参/返回值/子调用异常
line number
ByteBuddy OnMethodEnter
@OnMethodExit
@OnMethodExit#onThrowable()
this/args/return/throw
field
locals
传统AOP Enter
Exit
Exception
this/args/return/throw

2、实验-入参替换

对于ByteKit和bytebuddy进行了一次在agent场景下修改方法入参的实验,结合两者使用,就编码、调试方面进行对比总结。

2.1、 ByteKit

ByteKit的是直接在原方法中修改字节码,场景如下:
原方法:

    public String invokeList(List<String> list) {
   
   
        StringBuilder sb = new StringBuilder();
        sb.append("[");
        for (String s : list) {
   
   
            if(sb.length()>1){
   
   
                sb.append(", ");
            }
            sb.append(s);
        }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值