文章目录
- 前言
- 什么是.class文件
- 什么是ASM
- 概述
- 作用域
- 模型
- 基于ASM的程序架构
- ASM库结构
前言
本文翻译自ASM官方文档。
什么是.class文件
Java字节码文件(.class)是Java编译器编译Java源文件(.java)产生的目标文件。它是一种8位字节的二进制流文件, 各个数据项按顺序紧密的从前向后排列, 相邻的项之间没有间隙, 这样可以使得.class文件非常紧凑, 体积轻巧, 可以被JVM快速的加载至内存, 并且占据较少的内存空间。
.java文件在被Java编译器编译之后, 每个类都单独占据一个.class文件, 并且类中的所有信息都会在.class文件中有相应的描述, 由于.class文件很灵活, 它甚至比.java文件有着更强的描述能力。
每个.class文件也被称为一个已编译类。
什么是ASM
程序分析、生成和转换是可以在许多情况下使用的有用技术:
- 程序分析的范围从简单的语法解析到完整的语义分析,可以用来发现应用程序中的潜在错误,检测未使用的代码,对代码进行逆向工程,等等。
- 程序生成用于编译器。这包括传统的编译器,也包括用于分布式编程的存根或骨架编译器、即时编译器等。
- 程序转换可用于优化或混淆程序,在应用程序中插入调试或性能监视代码,用于面向切面编程等。
所有这些技术都可以用于任何编程语言。对于Java来说,它们可以用于Java源代码或已编译类。在已编译类上工作的一个优点是不需要源代码。因此,程序转换可以用于任何应用程序,包括闭源和商业应用程序。处理已编译类的另一个好处是,可以在运行时分析、生成或转换类,就在它们加载到Java虚拟机之前(当然,也可以在运行时生成和编译源代码,但这非常慢,并且需要一个完整的Java编译器)。
ASM就是一种被设计用于分析、生成和转换已编译类的工具,并且它还被设计得尽可能快、尽可能小。
概述
作用域
ASM库的目标是生成、转换和分析已编译类。为此,ASM提供了一些工具,通过使用比字节更高级的概念来读取、写入和转换字节数组,例如数字常量、字符串、Java标识符、Java类型、Java类结构元素等。请注意,ASM库的作用域严格限于读、写、转换和分析字已编译类,禁止将其用于类加载过程。
模型
ASM提供了两个用于生成和转换已编译类的API:
- 核心API提供基于事件的类表示:在基于事件的模型中,一个类用一系列事件表示,每个事件表示类的一个元素,比如一个字段、一个方法声明、一条指令等。基于事件的API定义了一组可能发生的事件以及它们必须发生的顺序,并提供了一个类解析器,它为被解析的每个元素生成一个事件,还提供了一个类编写器,它根据这些事件的序列生成已编译的类。
- 树API提供基于对象的表示:在基于对象的模型中,一个类用对象树表示,每个对象表示类的一部分,比如一个字段、一个方法、一条指令等,每个对象都有对表示其组成部分的对象的引用。基于对象的API提供了一种方法,可以将表示类的事件序列转换为表示同一类的对象树,反之亦然,也可以将对象树转换为等效的事件序列。换句话说,基于对象的API构建在基于事件的API之上。
这两个API各自有各自的优缺点:
- 基于事件的API比基于对象的API更快,并且需要更少的内存,因为不需要在内存中创建和存储表示类的对象树。
- 然而,使用基于事件的API实现类转换可能会更加困难,因为在任何给定时间,类中只有一个元素可用(与当前事件对应的元素),而使用基于对象的API,整个类在内存中可用。
请注意,这两个API一次只管理一个类,并且独立于其他类,也就是说:不维护有关类层次结构的信息,如果一个类的转换影响到了其他类,那么由用户来决定和修改这些其他类。
基于ASM的程序架构
基于事件的API围绕事件生产者(类解析器)、事件消费者(类编写器)和各种预定义的事件过滤器组织的,其中可以添加用户定义的生产者、消费者和过滤器。因此,使用这个API需要两个步骤:
- 将事件生产者、过滤器和消费者组件组装到可能复杂的体系结构中
- 然后启动事件生成器来运行生成或转换过程
基于对象的API可以组合在对象树上操作的类生成器或转换器组件,它们之间的链接表示转换的顺序。
尽管典型ASM应用程序中的大多数组件架构都相当简单,但可以想象如下复杂的架构,其中箭头表示类解析器,编写器或转换器之间基于事件或基于对象的通信,并在链中的任何位置进行基于事件和基于对象的表示之间的可能转换:
ASM库结构
ASM库被组织在几个包中,这些包分布在几个jar文件中:
org.objectweb.asm and org.objectweb.asm.signature
包定义了基于事件的API,并提供了类解析器和编写器组件,它被包含在asm.jar中。org.objectweb.asm.util
包提供了各种基于核心API的工具,可以在ASM应用程序的开发和调试过程中使用,它被包含在asm-util.jar中。org.objectweb.asm.commons
包提供了一些有用的预定义转换器,这些转换器大多基于核心API,它被包含在asm-commons.jar中。org.objectweb.asm.tree
包定义了基于对象的API,并提供了在基于事件和基于对象的表示之间进行转换的工具,它被包含在asm-tree.jar中。org.objectweb.asm.tree.analysis
包提供一个基于树的类分析框架和几个预定义的类分析器
API,它被包含在asm-analysis.jar中。
本文档分为两部分。第一部分介绍了核心API,即asm、asm-util和asm-commons。第二部分介绍了树API,即asm-tree和asm-analysis。每个部分至少包含一章与类相关的API,一章与方法相关的API,一章与注解、泛型类型等相关的API。每章都介绍了编程接口以及相关的工具和预定义的组件。所有示例的源代码都可以在ASM网站上找到。