首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

Presto 设计与实现(四): ByteBuddy

1. 原理

动态代码生成就是运行时通过编码的方式定义类的限定名、属性和方法等,并将其转化为可以被 ClassLoader 直接加载的 Java 字节码。

下面是从类的声明到使用的过程:

在 IDE 中创建 Java 类,声明类的构造函数、属性或方法等,Java 类以 .java 文件的形式存储;

通过 maven 命令或其他打包工具进行编译打包,.java 文件被编译成 .class 文件,.class 文件又打包成可执行的 jar 包或 war 包;

通过 Java 相关命令执行 jar 包或部署在 web 容器上运行,.class 文件转化为字节数组,被 ClassLoader 加载;

在实际使用时,由于类已经被 ClassLoader 加载,我们就可以创建类对象,使用类的相关方法实现某些业务功能。

而如果使用 ByteBuddy ,ByteBuddy 可以直接生成字节数组替换 .class 转化的所有过程。

2. 类的定义和加载

下面是我期望创建的类,该类只有一个属性 name,有 getName 和 setName 方法,重写 toString 返回 name:

复制代码

使用 ByteBuddy 如何创建呢?

复制代码

动态创建类的声明,之后将类的定义输出到文件中,下面是输出结果:

在此过程中有两个问题没有解决:

定义属性 name 后通过 value 方法设置初始值没有效果;

定义 setName 方法的参数名,想将 var1 设置为 name。

大家有思路的,欢迎留言指点。

类定义完毕后,就可以加载使用了:

复制代码

3. AOP

在调用 ByteBuddyTest -> toString 方法的前后,记录日志:

复制代码

步骤 1:声明一个静态方法,入参加上 @SuperCall 注解,使用 Callable 作为类型,里面的范型 T 就是方法实际的返回值。

复制代码

步骤 2:创建 ByteBuddy 实例匹配方法,创建 AOP 处理逻辑

复制代码

输出结果:

4. 重新加载类

对于一个已经加载的类,依然可以重新加载该类,改变类的既有实现。

复制代码

执行后的结果:

想想这功能也太 Bug 了,感觉有点反面向对象设计,除非特定场景,建议还是不要使用的好。

5. Java Agent 代理

ByteBuddy 还有个更有价值的用途:用于 Java Agent 的实现,通过 ByteBuddy 你可以全方位的监控拦截对象的创建和方法的调用。

你需要使用 ElementMatchers 进行匹配:

.type((ElementMatchers.any())):匹配所有类;

.type((ElementMatchers.nameContains("say"))):匹配包含特定方法的类;

.method(ElementMatchers.any()):匹配所有方法;

.method(ElementMatchers.nameContains("say")):匹配特定方法。

5.1 编写拦截器:方法调用前后的处理逻辑

开始前,你需要单独创建 Java Agent 项目。

复制代码

5.2 编写 Agent:匹配类、方法以及和拦截器的绑定

复制代码

5.3 构建架包

pom.xml 文件中添加打包插件:

复制代码

将所有依赖打成 1 个架包:

复制代码

5.4 应用

下面这个类用于测试,验证 Agent 是否可以工作, 类的构造函数和方法实际执行时会停留短暂时间:

复制代码

测试时添加 JVM 参数: :

开始执行,Agent 已经开始工作了:

6. ByteBuddy 在 Presto 中的使用

ByteBuddy 是构建在 ASM 之上的一款强大的 Java 字节码操纵工具,许多开源项目对其都有依赖,例如 Presto、Spark、Flink 和 Cassandra 等。

在 Presto 中 SQL 语句经过词法分析、语法分析会转变成一棵 AST 树,之后使用递归的方式结合访问者模式遍历树上的所有节点,访问者在访问的过程中会涉及到动态代码的生成,底层使用的就是 airlift.bytecode。

  • 发表于:
  • 原文链接https://page.om.qq.com/page/OTYIK8o3sr5ks2pIHys1PXkw0
  • 腾讯「腾讯云开发者社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 cloudcommunity@tencent.com 删除。

扫码

添加站长 进交流群

领取专属 10元无门槛券

私享最新 技术干货

扫码加入开发者社群
领券