Bytecode Manipulation
Transformer
In Booster, all bytecode-related operations are performed through Transformeropen in new window, which is a simple abstraction for bytecode transformation. It takes bytecode binary as input and outputs transformed bytecode binary. It is independent of which bytecode manipulation framework is used, allowing developers to choose specific implementations related to their preferred bytecode framework. Booster provides two implementations:
- ASM-based implementation: AsmTransformeropen in new window
- Javassist-based implementation: JavassistTransformeropen in new window
Custom Transformer
In addition to AsmTransformeropen in new window and JavassistTransformeropen in new window, Booster allows developers to implement their own Transformeropen in new window. Here's an example using 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()
}
}
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
Note that the constructor with ClassLoader parameter is not required, but it will affect loading custom ClassTransformer via ServiceLoader in BcelTransformer.
