b bytebuddy 之agentbuilder 的使用&API详解


使用中发现源码中的高阶用法根本看不懂,狠下心来试着结合文档和源码看下Agentbuilder。

  • 这篇文档会忽略java agent的基础知识,请自行百度。或者参考instrument
  • 对过于繁琐的代码,会说明意图,细节等。
  • 首先会介绍用法的模板,涉及bytebuddy的各个类的作用,请参考bytebuddy简单入门
  • 然后是按照类的结构来介绍Agentbuilder的功能。

希望我能写完吧,太难了。

一、使用范式:创建一个agent

当一个应用变得庞大和模块化时,使用java agent机制很合适。

定义transformer,每有一个类加载时,触发transformer逻辑,对类进行匹配和修改。

bytebuddy提供了Agentbuilder,封装了一系列API来新建一个 agent。
示例
假设我们定义了一个注解ToString,我们匹配所有标注@ToString的类,修改toString方法,让其返回"transformed"

class ToStringAgent {
   
  public static void premain(String arguments, Instrumentation instrumentation) {
   
    new AgentBuilder.Default()
        .type(isAnnotatedWith(ToString.class))
        .transform(new AgentBuilder.Transformer() {
   
      @Override
      public DynamicType.Builder transform(DynamicType.Builder builder,
                                              TypeDescription typeDescription,
                                              ClassLoader classloader) {
   
        return builder.method(named("toString"))
                      .intercept(FixedValue.value("transformed"));
      }
    }).installOn(instrumentation);
  }
}
  • type 接受 一个ElementMatcher 匹配 ToString注解
  • transform 接受AgentBuilder.Transformer 来描述修改逻辑
// 这里匹配类里面的`toString`方法,使用`intercept`修改返回值
 public DynamicType.Builder transform(DynamicType.Builder builder,
                                              TypeDescription typeDescription,
                                              ClassLoader classloader) {
   
        return builder.method(named("toString"))
                      .intercept(FixedValue.value("transformed"));
      }
  • installOn ,将修改,应用到instrumentation中。

二、AgentBuilder 类结构

bytebuddy的API

2.1 嵌套的内部类

order Modifier and Type Interface Description
0 static interface AgentBuilder.CircularityLock 一个循环锁,阻止ClassFileLocator被提前使用。发生在,一个 transformation逻辑可能会导致另外的类被加载。如果不避免这样的循环依赖,就会抛出ClassCircularityError错误,导致类加载失败
1 static interface AgentBuilder.ClassFileBufferStrategy 关于class定义的字节缓存buffer如何被使用的策略
2 static class AgentBuilder.Default AgentBuilder的默认实现。默认情况下,byte buddy 无视任何被bootstrap loader加载的类和合成类。1. Self-injection 和 rebase 模式开启 2. 为了避免class的格式发生改变,AgentBuilder.disableClassFormatChanges() 3. 所有的类型解析都是 PoolStrategy.Default#FAST,忽略所有的debug信息
3 static interface AgentBuilder.DescriptionStrategy 策略,描述当转化和定义一个类时,如何解决TypeDescription定义,这个解决指的是寻找+处理
4 static interface AgentBuilder.FallbackStrategy 失败策略,允许万一失败时,可以再次进行transformation或者redefine/retransformation。如果这样做了,可能就是会使用typepool,而不是一个已经加载的type description–相当于某个class的备份。如果class loader不能找到所有的依赖的类,会抛出异常。使用typepool,由于时懒加载,所以会规避异常,直到被使用
5 static interface AgentBuilder.Identified 用来描述AgentBuilder处理哪几种mathcer,这个就是提供给mather一个标识,便于筛选
6 static interface AgentBuilder.Ignored 允许声明,忽略那些具体的方法
7 static interface AgentBuilder.InitializationStrategy 初始化策略,决定LoadedTypeInitializer是如何加载辅助类。agentbuilder不能重用TypeResolutionStrategy策略,是因为Javaagents不能获取到一个被transformation过,已经加载的类。所以所以不同的初始化加载策略更有效
8 static interface AgentBuilder.InjectionStrategy 将辅助类注入classloader的策略
9 static interface AgentBuilder.InstallationListener 监听器,安装和重置class file transformer事件会唤醒这个监听器
10 static class AgentBuilder.LambdaInstrumentationStrategy lambda风格的语法特性开启
11 static interface AgentBuilder.Listener 一个an instrumentation 运行时会触发一堆事件,这个监听器是用来接受这些事件的
12 static interface AgentBuilder.LocationStrategy 修改一个类时,描述如何去创建ClassFileLocator的策略
13 static interface AgentBuilder.Matchable<T extends AgentBuilder.Matchable> 继承了mathcer的一个抽象实现,链式的结构
14 static interface AgentBuilder.PoolStrategy 描述AgentBuilder如何寻找和加载类TypeDescription的策略
15 static interface AgentBuilder.RawMatcher 一个matcher,用来匹配类并决定AgentBuilder.TransformerClassFileTransformer运行期间是否被使用
16 static interface AgentBuilder.RedefinitionListenable 允许在redefine的过程中注册一堆监听器
17 static class AgentBuilder.RedefinitionStrategy redefinition策略,描述agent如何控制已经被agent 加载到内存里面的类
18 static interface AgentBuilder.Transformer 应用DynamicType(定义的类修改),将DynamicType,对接到ClassFileTransformer
19 static interface AgentBuilder.TransformerDecorator AgentBuilder.Transformer的装饰器
20 static interface AgentBuilder.TypeStrategy 描述创建一个要被修改的类型,如何创建的方式

2.2 方法

相当于API的翻译,会有简单解释,觉得不准请看上面的API文档。

  • 加载过 往往意味值loaded,就是指classloader已经加载过目标类。bytebuddy通常就是感知类的加载,并且返回一个加工过的类。如此完成字节码修改的作用。
order return type method 描述
0 AgentBuilder with(ByteBuddy byteBuddy) ByteBuddy是用来创建DynamicType的。这里就是接受并生成一个AgentBuilder
1 AgentBuilder with(Listener listener) 注册监听器,创建agent的时候,会唤醒这个Listener。注意的是可以注册多个,如果早已经注册,也会重复唤醒,不会只唤醒一个
2 AgentBuilder with(CircularityLock circularityLock) 一个循环锁,被用于被执行的代码会加载新的类时,会获取这个锁。当锁被获取时,任何classfiletransformer都不能transforming 任何类,默认,所有被创建的agent都使用一个CircularityLock,避免造成一个ClassCircularityError。就是避免被执行的代码加载新类,同时其他agent也在转化这个类,造成一个循环依赖的一个锁
3 AgentBuilder with(PoolStrategy poolStrategy) 加载的类时的策略
4 AgentBuilder with(Locati
  • 7
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值