一、使用
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 | EnterExitException |
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);
}

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

992

被折叠的 条评论
为什么被折叠?



