ASM 字节码增强框架详解(上)

本文涉及的产品
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
云解析 DNS,旗舰版 1个月
全局流量管理 GTM,标准版 1个月
简介: ASM是Java中比较流行的用来读写字节码的类库,用来基于字节码层面对代码进行分析和转换。ASM是一个Java字节码操纵框架,它能被用来动态生成类或者增强既有类的功能。ASM可以直接产生二进制class文件,也可在类被加载入虚拟机之前动态改变类行为, ASM从类文件中读入信息后,能够改变类行为,分析类信息,甚至能根据要求生成新类。目前许多框架如cglib、Hibernate、 Spring都直接或间接使用ASM操作字节码。

1 概述

ASM是Java中比较流行的用来读写字节码的类库,用来基于字节码层面对代码进行分析和转换。


ASM是一个Java字节码操纵框架,它能被用来动态生成类或者增强既有类的功能。


ASM可以直接产生二进制class文件,也可在类被加载入虚拟机之前动态改变类行为, ASM从类文件中读入信息后,能够改变类行为,分析类信息,甚至能根据要求生成新类。目前许多框架如cglib、Hibernate、 Spring都直接或间接使用ASM操作字节码。


在读写的过程中可以加入自定义的逻辑以增强或修改原来已编译好的字节码,比如CGLIB用它来实现动态代理。ASM被设计用于在运行时对Java类进行生成和转换,当然也包括离线处理。ASM短小精悍、且速度很快,从而避免在运行时动态生成字节码或转换时对程序速度的影响,又因为它体积小巧,可以在很多内存受限的环境中使用。

ASM的主要优势包括如下几个方面:

  1. 它又一个很小,但设计良好并且模块化的API,且易于使用。
  2. 它具有很好的文档,并且还有eclipse插件。
  3. 它支持最新的Java版本。
  4. 它短小精悍、快速、健壮。
  5. 它又一个很大的用户社区,可以给新用户提供支持。
  6. 它的开源许可允许你几乎以任何方式来使用它。

编程模型

  • Core API
    提供了基于事件形式的编程模型。该模型不需要一次性将整个类的结构读取到内存中,因此这种方式更快,需要更少的内存,但这种编程方式难度较大
  • Tree API
    提供了基于树形的编程模型。该模型需要一次性将一个类的完整结构全部读取到内存当中,所以这种方法需要更多的内存,这种编程方式较简单

ASM Core设计

主要有以下几个类、接口(org.objectweb.asm包):

  • ClassReader类:字节码的读取与分析引擎。它采用类似SAX的事件读取机制,每当有事件发生时,调用注册的ClassVisitor、AnnotationVisitor、FieldVisitor、MethodVisitor做相应的处理
  • ClassVisitor接口:该接口中的每个方法,对应了 class 文件中的每一项。定义在读取Class字节码时会触发的事件,如类头解析完成、注解解析、字段解析、方法解析等。 解析器使ClassVisitor访问 JVMS 中定义的Class文件结构。 此类解析ClassFile内容,并为遇到的每个字段,方法和字节码指令调用给定ClassVisitor的适当访问方法。
  • ClassAdapter
    ClassAdapter是ClassVisitor的实现类,实现要变化的功能
  • AnnotationVisitor接口:定义在解析注解时会触发的事件,如解析到一个基本值类型的注解、enum值类型的注解、Array值类型的注解、注解值类型的注解等
  • FieldVisitor接口:定义在解析字段时触发的事件,如解析到字段上的注解、解析到字段相关的属性等。
    MethodVisitor接口:定义在解析方法时触发的事件,如方法上的注解、属性、代码等。
  • ClassWriter类
    它实现了ClassVisitor接口,用于拼接字节码,输出变化后的字节码
  • AnnotationWriter类:它实现了AnnotationVisitor接口,用于拼接注解相关字节码
  • FieldWriter类:它实现了FieldVisitor接口,用于拼接字段相关字节码
  • MethodWriter类:它实现了MethodVisitor接口,用于拼接方法相关字节码。
  • SignatureReader类:对类定义、字段定义、方法定义、本地变量定义的签名的解析。Signature因范型引入,用于存储范型定义时的元数据(因为这些元数据在运行时会被擦除)。
  • SignatureVisitor接口:定义在解析Signature时会触发的事件,如正常的Type参数、类或接口的边界等。
    SignatureWriter类:它实现了SignatureVisitor接口,用于拼接范型相关字节码。
  • Attribute类:字节码中属性的类抽象。
  • ByteVector类:字节码二进制存储的容器。
  • Opcodes接口:字节码指令的一些常量定义。
  • Type类:类型相关的常量定义以及一些基于其上的操作。

类图关系

ClassReader是ASM中最核心的实现,它用于读取并解析Class字节码

image.png

在构建ClassReader实例时,它首先保存字节码二进制数组b,然后创建items数组,数组的长度在字节码数组的第8、9个字节指定(最前面4个字节是魔数CAFEBABE,之后2个字节是次版本号,再后2个字节是主版本号),每个item表示常量池项在字节码数组的偏移量加1(常量池中每个项由1个字节的type和紧跟的字节数组表示,常量池项有12种类型,其中CONSTANT_FieldRef_Info、CONSTANT_MethodRef_Info、CONSTANT_InterfaceMethodRef_Info、CONSTANT_NameAndType_Info包括其类型字节占用5个字节,另外4个字节每2个字节为字段、方法等所在的类、其名称、描述符在当前常量池中CONSTANT_Utf8_Info类型的引用;CONSTANT_Integer_Info、CONSTANT_Float_Info包括其类型字节占用5个字节,另外四个字节为其对应的值;CONSTANT_Class_Info、CONSTANT_String_Info包括其类型字节占用3个字节,另外两个字节为在当前常量池CONSTANT_Utf8_Info项的索引;CONSTANT_Utf8_Info类型第1个字节表示类型,第2、3个字节为该项所表示的字符串的长度);CONSTANT_Double_Info、CONSTANT_Long_Info加类型字节为9个字;maxStringLength表示最长的UTF8类型的常量池项的值,用于决定在解析CONSTANT_Utf8_Info类型项时最大需要的字符数组;header表示常量池之后的字节码的第一个字节。


目录
相关文章
|
11月前
|
安全 算法 Java
从零开发基于ASM字节码的Java代码混淆插件XHood
因在公司负责基础框架的开发设计,所以针对框架源代码的保护工作比较重视,之前也加入了一系列保护措施,例如自定义classloader加密保护,授权license保护等,但都是防君子不防小人,安全等级还比较低,经过调研各类加密混淆措施后,决定自研混淆插件,自主可控,能够贴合实际情况进行定制化,达到框架升级后使用零感知,零影响
115 1
从零开发基于ASM字节码的Java代码混淆插件XHood
|
4月前
|
Java API Android开发
ASM 框架:字节码操作的常见用法(生成类,修改类,方法插桩,方法注入)
ASM 框架:字节码操作的常见用法(生成类,修改类,方法插桩,方法注入)
76 0
|
4月前
|
存储 算法 Java
ASM字节码操纵框架实现AOP
ASM字节码操纵框架实现AOP
40 0
|
4月前
|
存储 算法 Java
Android 进阶——代码插桩必知必会&ASM7字节码操作
Android 进阶——代码插桩必知必会&ASM7字节码操作
179 0
|
4月前
|
Java Kotlin
ASM字节码插桩实现点击防抖
ASM字节码插桩实现点击防抖
32 0
|
存储 监控 Java
字节码插桩(三): ASM 字节码插桩(1)
字节码插桩(三): ASM 字节码插桩
238 0
字节码插桩(三): ASM 字节码插桩(1)
|
存储 算法 Java
一起来学字节码插桩:ASM Tree API
`ASM`是一个通用的`Java字节码操作和分析框架`。它可用于`修改现有类`或`直接以二进制形式动态生成类`。`ASM`提供了一些常见的字节码转换和分析算法,可以根据这些算法构建定制的复杂转换和代码分析工具。
264 0
|
Java API 开发工具
字节码插桩(三): ASM 字节码插桩(2)
字节码插桩(三): ASM 字节码插桩(2)
135 0
|
Java fastjson 数据库连接
字节码操作框架介绍与实践(以ASM和Javassit为例)
ASM是java字节码操作领域公认的标准,被众多知名的开源框架使用,如cglib、mybatis,fastjson等。通过ASM提供的API,我们可以方便的修改类文件的字节码,并ASM会自动帮我们做很多事情,如维护常量池的索引、计算栈大小max_stack,局部变量表大小max_locals等。ASM提供了两种类型的API,基于事件触发的core api和基于对象的tree api,下面主要介绍基
1225 0
字节码操作框架介绍与实践(以ASM和Javassit为例)
|
5月前
|
Oracle 关系型数据库
oracle asm 磁盘显示offline
oracle asm 磁盘显示offline
257 2