Bytecode Manipulation
Transformer
在 Booster 中,跟字节码相关的操作都是通过 Transformeropen in new window 来完成,它是对字节码转换的简单抽象,以字节码的二进制做为输入,经过转换后,输出字节码二进制,它与具体使用哪种字节码操作框架无关,开发者可以自己选择跟字节码操作框架相关的特定实现, Booster 提供了两种实现:
- 基于 ASM 的实现:AsmTransformeropen in new window
- 基于 Javassist 的实现:JavassistTransformeropen in new window
Custom Transformer
除了 AsmTransformeropen in new window 和 JavassistTransformeropen in new window 外,Booster 允许开发者实现自己的 Transformeropen in new window,以 Apache Commons BCELopen in new window 为例:
interface ClassTransformer : TransformerListener {
fun transform(context: TransformContext, klass: JavaClass) = klass
}
@AutoService(Transformer::class)
class BcelTransformer(val classLoader: ClassLoader) : Transformer {
private val transformers = ServiceLoader.load(ClassTransformer::class.java, classLoader).sortedBy {
it.javaClass.getAnnotation(Priority::class.java)?.value ?: 0
}
override fun onPreTransform(context: TransformContext) {
this.transformers.forEach { transformer ->
transformer.onPreTransform(context)
}
}
override fun onPostTransform(context: TransformContext) {
this.transformers.forEach { transformer ->
transformer.onPostTransform(context)
}
}
override fun transform(context: TransformContext, bytecode: ByteArray): ByteArray {
return ClassParser(bytecode.inputStream(), "").parse().run { klass ->
TODO("Transform JavaClass with BCEL")
}.getBytes()
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
TIP
需要注意的是,带 ClassLoader
参数的构造方法不是必须的,但会影响在 BcelTransformer 中通过 ServiceLoader
加载自定义的 ClassTransformer。