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

无处不在的字节码技术-ASM在cglib和fastjson中的应用

字节码技术在我们常见的各大框架中都有用到. 这篇文章我们将讲解 ASM 在 cglib 和 fastjson 上的实际使用案例。

cglib 的简单应用

如果说 ASM 是字节码改写事实上的标准,那么可以说 cglib 则是动态代理事实上的标准。cglib 是一个强大的、高性能的代码生成库,被大量框架使用

Spring:为基于代理的 AOP 框架提供方法拦截

MyBatis:用来生成 Mapper 接口的动态代理实现类

Hibernate:用来生成持久化相关的类

Guice、EasyMock、jMock 等在实现内部,cglib 库使用了 ASM 字节码操作框架来转化字节码,产生新类,帮助开发者屏蔽了很多字节码相关的内部细节,不用再去关心类文件格式、指令集等

有这样一个 Person 类,想在 doJob 调用前和调用后分别记录一些日志

我们可以使用 JDK 动态代理来实现,不过介于 JDK 动态代理有个明显的缺点(需要目标对象实现一个或多个接口),在这里重点介绍 cglib 的实现方案。一个典型的实现方案是实现一个 接口,用来拦截方法调用。这个接口只有一个方法:

这个方法的第一个参数 obj 是代理对象,第二个参数 method 是拦截的方法,第三个参数是方法的参数,第四个参数 proxy 用来调用父类的方法。MethodInterceptor 作为一个桥梁连接了目标对象和代理对象

cglib 代理的核心是 类,它用于创建一个 cglib 代理。这个类有一个静态方法,该方法的第一个参数 type 指明要代理的对象类型,第二个参数 callback 是要拦截的具体实现,一般都会传入一个 MethodInterceptor 的实现

运行上面的代码输出:

可以用设置系统变量让 cglib 输出生成的文件

核心类是 ,这个类的反编译以后的代码如下

可以看到 cglib 生成了一个 Person 的子类,实现了 doJob 方法,此方法会调用 MethodInterceptor 的 intercept 函数,这个函数先输出 ">>>>>before intercept" 然后调用父类(也即真正的 Person 类)的 doJob 的方法,最后输出

FastJson

fastjson 是目前 java 语言中最快的 json 库,比自称最快的 jackson 速度要快。fastjson 库内置 ASM,基于 objectweb asm 3.3 改造,只保留必要的部分不到 2000 行代码,通过 ASM 自动生成序列号、反序列化字节码,减少反射开销,理论上可以提高 20% 的性能。如果不用反射,一个 json 反序列化要怎么样来做呢?下面写了一个最简单粗暴的例子,来反序列化下面的 json 字符串

假定不考虑嵌套,特殊字符的情况,不做语法解析的情况下,可以这么来写

可以看到获取获取字段 field、设置字段值都需要通过反射的方式。那么 fastjson 是怎么解决反射低效的问题的呢?通过调试的方式,把 fastjson 生成的字节码写入到文件中。针对 MyBean,fastjson 使用 ASM 为它生成了一个反序列化的类,里面硬编码了处理序列化需要用到的所有可能场景,不再需要任何反射相关的代码。结合创新的 sort field fast match 算法,速度更上一层楼。下面是通过阅读字节码精简以后的 Java 代码。

通过上面的两个例子,我们可以看到 ASM 字节码技术在底层库上的强大。可能每天写业务代码不会需要使用这些底层的优化,但是当我们想造一个轮子,想读懂开源代码背后的核心时,都不得不深入的去学习了解这部分知识,很难,但很值得。

小结

这篇文章我们主要讲解了 ASM 字节码改写技术在 cglib 和 fastjson 上的应用,一起来回顾一下要点:

第一,cglib 使用 ASM 生成了目标代理类的一个子类,在子类中扩展父类方法,达到代理的功能,因此要求代理的类不能是 final 的。

第二,fastjson 使用 ASM 生成了实例 Bean 反序列化类,彻底去掉了反射的开销,使性能更上一层楼。

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

扫码

添加站长 进交流群

领取专属 10元无门槛券

私享最新 技术干货

扫码加入开发者社群
领券