Bytecode Manipulation

Transformer

Booster 中,跟字节码相关的操作都是通过 Transformeropen in new window 来完成,它是对字节码转换的简单抽象,以字节码的二进制做为输入,经过转换后,输出字节码二进制,它与具体使用哪种字节码操作框架无关,开发者可以自己选择跟字节码操作框架相关的特定实现, Booster 提供了两种实现:

  1. 基于 ASM 的实现:AsmTransformeropen in new window
  2. 基于 Javassist 的实现:JavassistTransformeropen in new window

Custom Transformer

除了 AsmTransformeropen in new windowJavassistTransformeropen 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

TIP

需要注意的是,带 ClassLoader 参数的构造方法不是必须的,但会影响在 BcelTransformer 中通过 ServiceLoader 加载自定义的 ClassTransformer