Class 文件结构
类似于 C 结构体描述,统一用无符号整数作为基本数据类型
u1、u2、u4、u8 表示无符号单字节、2 、4 、8 字节,字符串用 u1 数组进行表示
|
|
Magic Number
固定为 0xCAFEBABE
文件版本
major version | jdk |
---|---|
51 | 1.7 |
52 | 1.8 |
常量池
Class 文件中内容最为丰富的区域之一,是整个 Class 文件的基石
对于 Class 文件中的字段和方法解析也有着至关重要的作用
常量池 0 保留项,不存实际内容
不同类型的常量项的内容内容结构各不相同,一般都是以 “类型-长度-内容” 或者 “类型-内容” 的格式依次排列
常量池类型 | Tag | 常量池类型 | Tag |
---|---|---|---|
Utf8 | 1 | Fieldref | 9 |
Integer | 3 | Methodref | 10 |
Float | 4 | InterfaceMethodref | 11 |
Long | 5 | NameAndType | 12 |
Double | 6 | MethodHandle | 15 |
Class | 7 | MethodType | 16 |
String | 8 | InvokeDynamic | 18 |
常量池的描述方式总结一下就是:每一项要么直接包含了所要描述的内容,比如 utf8 字符串,要么以编号的形式引用其他项的内容
|
|
字节码技术
节码增强:
对现有字节码修改或动态生成全新字节码文件,一般用来实现AOP
字节码增强技术,可以选择的类库有很多
ASM
Cglib 就是基于 ASM
ASM 有两套 API
-
Core API
基于 访问者模式
不需要把这个类的整个结构读取进来,就可以用流式的方法来处理字节码文件
MethodVisitor、FieldVisitor、AnnotationVisitor 等
AOP,重点要使用的是 MethodVisitor
-
Tree API
将字节码中的各个结构抽象成一个树形结构,通过 Tree API 可以直接修改该树形结构
把整个类的结构读取到内存中
通过各种 Node 类来映射字节码的各个区域
|
|
|
|
新类反编译后
|
|
Javassist
ASM 在 指令层次上操作字节码
,实现起来比较繁琐
Javassist 强调源代码层次操作字节码
直接使用 java 编码,不需解虚拟机指令,就能动态改变类的结构或者动态生成类
-
CtClass(compile-time class):
编译时类信息,它是一个 class 文件在代码中的抽象表现形式,可以通过一个类的全限定名来获取一个 CtClass 对象,用来表示这个类文件
-
ClassPool:
从开发视角来看,ClassPool 是一张保存 CtClass 信息的 HashTable,key 为类名,value 为类名对应的 CtClass 对象
pool.getCtClass(“className”)从 pool 中获取到相应的 CtClass
-
CtMethod、CtField:
对应类中的方法和属性
|
|