提起 JavaAgent,很多人都说几句,就像古龙武侠小说里的「孔雀翎」,威力很大,江湖上都是它的传说。但真的见识过的人并没几个。
JavaAgent 虽说没这么神秘,但也一直给人曲高和寡的感觉,除了一些中间件产品、大型的框架中使用外,在业务中一直很少出现。
原因可能有很多,一来是可能确实不需要,再者需要开发独立的 Agent Jar 文件,在 Jar 内对类的 transform 开发也并不容易。
我们知道,无论是启动时的 Java Agent,还是运行时的动态 attach 到远程JVM, 都是为了拿到 Instrument,对 class 的字节码进行修改。这么底层的东西,当然使用起来让人不太容易下手。
不过就像机器语言不方便,人们发明了汇编语言,又发现了高级语言。对于字节码的操作也类似,人们觉得直接操作字节码有难度,而且需要深入理解 JVM 规范,具体什么位置多少字节代表啥,这不是一般人喜欢的,于是 ASM 框架出现了;但还是有规范的影子,不太「高级」,于是又出现了Javassist 这一类的「高级」工具。
我们今天要说的这个工具,和 Javassist 类似,都提供了更高层的API,来操作class,对普通程序员更友好,除此之外呢?
就像今天人们购物、读书等,都更相信专业的平台、或者专家的推荐,像XX严选,XX读书会推荐。今天说的这个工具是Duke 的推荐,对,就是它, Java 的吉祥物,这个小胖子。今天的这个工具在 2015年被 Oracle 评选为「Duke's Choice award」。
除了Duke,框架也得到了众多开发者的认可,每年有七千多万次的下载。
这个工具是:Bytebuddy。
从名字你就看的出来,它立志要做字节码的好伙伴。所以在很多开源框架里也能看到它的身影。
既然已经有了不少的工具, byteBuddy能带来什么不一样呢?
除了API 上的简洁易操作,官方自己也大字强调了运行时动态的「代码生成和字节码操作」,不需要再借助 Java 编译器。
来看看官网是怎么自我介绍的,后面再附上几个代码片段,就能很快 Get 到了。
Byte Buddy is a code generation and manipulation library for creating and modifying Java classes during the runtime of a Java application and without the help of a compiler. Other than the code generation utilities that ship with the Java Class Library, Byte Buddy allows the creation of arbitrary classes and is not limited to implementing interfaces for the creation of runtime proxies. Furthermore, Byte Buddy offers a convenient API for changing classes either manually, using a Java agent or during a build.
阅读理解开始。重点你一定会看到了:
作者贴心的加了一段小字来描述框架的优势。选重点的说就是:
我自己认为该把这点也加上,不写 Java Agent 也可以 Attach 到 JVM 上,把 ByteBuddy 自己当成一个Agent,运行时直接install。Cool。
不写JVM Agent 也能对类拦截和修改,我们来认识下揭开字节码修改黑魔法的家伙。
为了对 Class 进行一些操作,我们一般都离不了 JVM Agent。不管是启动时直接连接,还是运行时动态的 Attach到对应的JVM 上,都需要 Agent。也就是我们熟悉的premain
和 agentmain
的触发入口,通过它们,我们才能拿到 Instrumentation
,从而进行 transform
和 redeine
。
但这个东西的使用,给人总是「阳春白雪」的感觉,让人觉得是黑魔法一样,一般不会轻易尝试使用。
有了ByteBuddy,就不用再羡慕一些框架的「运行时增强」,「动态织入」等等,都可以实现。
如何上手呢?
只需要下载 Jar 文件或者 Maven 添加依赖之后就能狂奔了。
比如官方的这个 HelloWorld
Class<?> dynamicType = new ByteBuddy()
直接把 Object 的 toString 方法改写了。
再比如我们可以在开发 Java Agent的时候使用这个伙计
public static void premain(String args, Instrumentation inst) {
在类里进行拦截匹配的时候,可以通过类名来限定,同时以不同的模式去匹配方法名等,这里的ElementMatchers可以用在类名与方法名等匹配场景中
//ElementMatchers.named("abc") // 特定名称的方法
我们看到前面的代码中 agentBuilder.installOn(inst);
通过 JavaAgent的Instrument 进行类修改。
AgentBuilder 还提供了一个神奇的方法:
agentBuilder.installOnByteBuddyAgent();
这样无须提供 Jar 文件也一样能实现运行时增强。不过需要注意,这样使用时,一定要先执行这行代码,这也是其实现的秘密:
ByteBuddyAgent.install();
因为 ByteBuddy 自己做为一个 Jar 也 Attach ,然后再将其它后续的增强代码加入,像不像「特洛伊木马」 :)
另外, ByteBuddy 还支持类似于 AOP 的 Advice实现,在拦截指定方法后可以实现OnMethodEnter 和 OnMethodExit 的控制,在这其中,可以完成绕过用户代码,执行自定义内容的逻辑。
咱们在开始的时候,还提到了代码的生成。这在 ByteBuddy 看来也是易如反掌。
和上面的代码一样,先要拿到 AgentBuilder,之后在执行 tranform的时候,直接指定方法名,以及对应的参数,访问控制符等。
DynamicType.Builder.MethodDefinition.ExceptionDefinition<?> hello =
再比如在运行时给一个方法增加注解,
builder.method(ElementMatchers.named("methodName")).intercept(SuperMethodCall.INSTANCE)
是不是功能很强大?
更多的用法,可以参考官方的Github或者官网。
欢迎交流。
相关阅读
Java七武器系列长生剑 -- Java虚拟机的显微镜 Serviceability Agent
嵌套事务、挂起事务,Spring 是怎样给事务又实现传播特性的?
源码|实战|成长|职场
这里是「Tomcat那些事儿」
请留下你的足迹
我们一起「终身成长」
原网址: 访问
创建于: 2020-11-11 09:27:06
目录: default
标签: 无
未标明原创文章均为采集,版权归作者所有,转载无需和我联系,请注明原出处,南摩阿彌陀佛,知识,不只知道,要得到
java windows火焰图_mob64ca12ec8020的技术博客_51CTO博客 - 在windows下不可行,不知道作者是怎样搞的 监听SpringBoot 服务启动成功事件并打印信息_监听springboot启动完毕-CSDN博客 SpringBoot中就绪探针和存活探针_management.endpoint.health.probes.enabled-CSDN博客 u2u转换板 - 嘉立创EDA开源硬件平台 Spring Boot 项目的轻量级 HTTP 客户端 retrofit 框架,快来试试它!_Java精选-CSDN博客 手把手教你打造一套最牛的知识笔记管理系统! - 知乎 - 想法有重合-理论可参考 安宇雨 闲鱼 机械键盘 客制化 开贴记录 文本 linux 使用find命令查找包含某字符串的文件_beijihukk的博客-CSDN博客_find 查找字符串 ---- mac 也适用 安宇雨 打字音 记录集合 B站 bilibili 自行搭建 开坑 真正的客制化 安宇雨 黑苹果开坑 查找工具包maven pom 引用地 工具网站 Dantelis 介绍的玩轴入坑攻略 --- 关于轴的一些说法 --- 非官方 ---- 心得而已 --- 长期开坑更新 [本人问题][新开坑位]关于自动化测试的工具与平台应用 机械键盘 开团 网站记录 -- 能做一个收集的程序就好了 不过现在没时间 -- 信息大多是在群里发的 - 你要让垃圾佬 都去一个地方看难度也是很大的 精神支柱 [超级前台]sprinbboot maven superdesk-app 记录 [信息有用] [环境准备] [基本完成] [sebp/elk] 给已创建的Docker容器增加新的端口映射 - qq_30599553的博客 - CSDN博客 [正在研究] Elasticsearch, Logstash, Kibana (ELK) Docker image documentation elasticsearch centos 安装记录 及 启动手记 正式服务器 39 elasticsearch 问题合集 不断更新 6.1.1 | 6.5.1 两个版本 博客程序 - 测试 - bug记录 等等问题 laravel的启动过程解析 - lpfuture - 博客园 OAuth2 Server PHP 用 Laravel 搭建带 OAuth2 验证的 RESTful 服务 | Laravel China 社区 - 高品质的 Laravel 和 PHP 开发者社区 利用Laravel 搭建oauth2 API接口 附 Unauthenticated 解决办法 - 煮茶的博客 - SegmentFault 思否 使用 OAuth2-Server-php 搭建 OAuth2 Server - 午时的海 - 博客园 基于PHP构建OAuth 2.0 服务端 认证平台 - Endv - 博客园 Laravel 的 Artisan 命令行工具 Laravel 的文件系统和云存储功能集成 浅谈Chromium中的设计模式--终--Observer模式 浅谈Chromium中的设计模式--二--pre/post和Delegate模式 浅谈Chromium中的设计模式--一--Chromium中模块分层和进程模型 DeepMind 4 Hacking Yourself README.md update 20211011
Laravel China 简书 知乎 博客园 CSDN博客 开源中国 Go Further Ryan是菜鸟 | LNMP技术栈笔记 云栖社区-阿里云 Netflix技术博客 Techie Delight Linkedin技术博客 Dropbox技术博客 Facebook技术博客 淘宝中间件团队 美团技术博客 360技术博客 古巷博客 - 一个专注于分享的不正常博客 软件测试知识传播 - 测试窝 有赞技术团队 阮一峰 语雀 静觅丨崔庆才的个人博客 软件测试从业者综合能力提升 - isTester IBM Java 开发 使用开放 Java 生态系统开发现代应用程序 pengdai 一个强大的博主 HTML5资源教程 | 分享HTML5开发资源和开发教程 蘑菇博客 - 专注于技术分享的博客平台 个人博客-leapMie 流星007 CSDN博客 - 舍其小伙伴 稀土掘金 Go 技术论坛 | Golang / Go 语言中国知识社区
最新评论