-
-
Notifications
You must be signed in to change notification settings - Fork 5
CLocalVariable
With CLocalVariable
you can capture local variables and use them in CTransformers.
When setting modifiable
to true
you can change the value of the variable and it will get copied back to the target method.
There are three ways to specify the target variable:
- Name in the local variable table
- Ordinal of the variable in the local variable table
- Load/Store variable index
The priority is in the order listed above. The first one that is present in the class file will be used.
The name and ordinal required the local variable table to be present in the class file. This may not be the case for obfuscated code.
The load/store variable index works without the local variable table but is harder to figure out and breaks faster when the code of the target method changes.
If none of the three are specified the name of the parameter will be used as the name in the local variable table.
If the name of the parameter cannot be found an exception will be thrown.
public void test(@CLocalVariable(name = "varName") String varName)
This will use the variable with the name varName
in the local variable table of the target method.
public void test(@CLocalVariable(name = "varName") String varName)
This will use the first String
variable in the local variable table of the target method.
public void test(@CLocalVariable(index = 1) String varName)
This will use the variable with the index 1
in the target method.
If ClassTransform can't figure out the type of the variable itself you need to specify the opcode in the loadOpcode
field.
Example:
public void test(@CLocalVariable(index = 1, loadOpcode = Opcodes.ALOAD) String varName)
If the modifiable
field is set to true
the value of the variable will be copied back to the target method after the transformer is done.
The default for this is false
as it may not be clear immediately that the variable will be modified.
Example:
public void test(@CLocalVariable(name = "varName", modifiable = true) String varName)
Original method:
public String method(final String arg) {
return "hello " + arg;
}
Transformer method:
//Capture the String argument of the method
@CInject(method = "method", target = @CTarget("HEAD"))
public void transform(@CLocalVariable(modifiable = true) String arg) {
//Your IDE may complain about the variable not being used
arg = "world";
}
Injected code:
public String method(final String arg) {
Object[] capturedLocals = new Object[1];
capturedLocals[0] = arg;
transform(capturedLocals);
arg = (String) capturedLocals[0]; //This part is skipped if the variable is not modifiable
return "hello " + arg;
}
//ClassTransform automatically remapped the transformer method to use an Object[]
public void transform(Object[] capturedLocals) {
capturedLocals[0] = "world";
}
ClassTransform automatically merges all the captured locals into an array to copy them back to the target method.
The merging of parameters is always done no matter if any of them are modifiable.