ASM3.0学习(一)

1、简述java

用于生成和转换编译后的java类,动态生成java 字节码,生成class文件。数组

2、使用描述3d

编译后的java类包含如下几部分:
 一个用于描述修饰符(public或者private),类名,父类名称,所实现的接口名称以及类注解的段。
 一个用于描述类中字段信息的段。每一个这样的段中都描述了字段的修饰符,名称,类型以及与该字段相关的注解。
 一个用于描述方法和构造方法的段。每一个段描述了方法的名称,返回值,参数类型以及方法的注解。同时也包含了方法编译后的字节码序列。blog

在源代码和编译后的代码之间,仍是存在一些不一样:
 一个编译后的java类仅仅只描述一个类信息,可是一个java源文件能够包含几个java类。例如,一个源文件能够定义一个包含内部类的java类,而编译后将会成为两个类文件,其中一个是主要的java类,另一个是内部类。在主要的类中包含了指向内部类的引用,同时在主要的java类的方法中定义的内部类也会包含一个指向该java方法的引用。
 一个编译后的java类不包含注释,固然,能够包含与类、字段、方法或者代码相关的属性,而这些属性能够用来关联一些额外的信息。在java 5中引入了注解之后,这些注解也能够实现一样的目的,所以,这些属性就变得不那么重要了。
 一个编译后的java类不包含package和import段,所以,在编译后的类中,全部的类型名称都必须使用全路径。接口

 

类的具体结构请参看java虚拟机规范第四段事件

编译后的java类总体结构(*表示0或者更多)文档

2.1.2内部名称
在不少状况下,一个类型限于一个java类或者结构表示的类型,例如,一个类的父类,一个类所实现的接口,一个方法所抛出的异常(不多是基本类型)或者数组,这些都是类或者接口类型。这些类型在编译后的类中之内部名称表示。一个类的内部名称就是这个类的全路径名称,将包名中的点号替换为/。例如,String的内部名称为java/lang/String。字符串

2.1.3类型描述符
内部名称仅用做一个类或者接口的类型,全部其余的,如字段类型,java基本类型都是以类型描述符来表示的,见图2.2
 类型描述符:虚拟机


基本类型的描述符:Z表示boolean,C表示char,B表示byte,I表示int,F表示float,J表示long,D表示double。一个类的描述符就是这个类的内部名称,在前面加上一个L,在后面加上一个分号便可。例如,String的类型描述符就是Ljava/lang/String.最后,一个数组的类型描述符就是一个中括号[后面跟上数组元素的类型描述符。it

2.1.4方法描述符
一个方法描述符就是一个包含参数类型的描述符,以及方法返回类型描述符的字符串。一个方法描述符以一个左括号开始,而后跟上每一个参数的描述符,而后是一个右括号,最后就是返回值的类型描述符,若是一个方法的返回值是void,那么返回值的类型描述符就是V(一个方法描述符不包含这个方法的名称以及参数的名称)。
方法描述符示例


一旦你知道了类型描述符如何工做,那么理解方法描述符很容易。例如,(I)I描述了这样一个方法,它有一个int类型的参数,以及一个int返回值。图2.3给出了几个方法描述符的例子。

2.2接口和组件
2.2.1表现(Presentation)
生成和转换编译后的类的ASM API是基于ClassVisitor接口的(见图2.4)。在这个接口中的每个方法都与类文件中有着相同名称的段相对应(见图2.1)。在访问类结构中简单的段时,是经过调用一个独立的方法来实现的,该方法的参数就是该段相关的内容,该方法的返回值为void。对长度任意而且较复杂的段进行访问时,是经过一个初始化方法返回一个辅助的visitor接口来实现,例如visitAnnotation,visitField以及visitMethod,它们都返回与之对应的接口AnnotationVisitor,FieldVisitor以及MethodVisitor。
这些规则也一样适用于这些辅助接口。例如,在FieldVisitor接口中的每一个方法,都与类文件结构中与该名称(Field)对应的子结构对应(见图2.5),而且visitAnnotation并会一个辅助的AnnotationVisitor接口,与ClassVisitor中的AnnotationVisitor相同。关于这些辅助接口的建立和使用,将在下一章节介绍,这一章主要限于那些简单的问题,使用ClassVisitor接口就能够解决的。
图2.4 ClassVisitor接口


图2.5 FieldVisitor接口

对ClassVisitor接口中方法的调用必须遵循下面文档定义的顺序,该文档定义在ClassVisitor 接口的Javadoc中。 visit visitSource? visitOuterClass? ( visitAnnotation | visitAttribute )*( visitInnerClass | visitField | visitMethod )* visitEnd 这就意味着visit必须被第一个调用,而后调用visitSource方法,最多调用一次,再接着是visitOuterClass,而后再调用任意次数的visitAnnotation或者visitAttribute方法,接着能够调用任意次数的visitInnerClass,visitiField或者visitMethod,顺序不限,在最后,调用visitEnd方法。 在ClassVisitor接口的基础上,ASM提供了三个组件来生成和转换类:  ClassReader 用来解析编译过的class的字节数组。而后,调用ClassVisitor实例的visitXxx方法,其中ClassVisitor实例做为ClassReader.accept方法的参数传递进去的。ClassReader能够被看作是一个事件产生者。  ClassWriter是ClassVisitor接口的一个实现,用来以二进制方式构建编译后的类。它产生一个包含编译后的类的字节数组,能够经过它的toByteArray方法来或得。它能够被看作是一个事件消费者。  ClassAdapter也是ClassVisitor接口的一个实现,它将对它的方法调用委托给另外一个ClassVisitor。它能够被认为是一个事件过滤器。 接下来,将结合具体的例子来展现如何使用这些组件来生成和转换类。

相关文章
相关标签/搜索