-
-
Notifications
You must be signed in to change notification settings - Fork 5
CTarget
The CTarget
annotation specifies the position in the method to inject into.
The value
field of the annotation specifies the type of the target. Depending on the type, the target
field has to be used to provide more information on the target.
By default, the shift
field is set to AFTER
which means the injection will be performed after the target, but it can be changed to BEFORE
which is the default behavior of Mixins.
The ordinal
allows choosing the target if multiple targets are available. If the ordinal is not set, all targets will be used.
A target can be made optional by setting the optional
field to true
. If the target is not found, the injection will be skipped instead of throwing an exception.
The following types are built-in:
Type | Target | Supported shifts | Target information |
---|---|---|---|
HEAD |
The first instruction in the method | BEFORE |
|
RETURN |
All return statements | BEFORE |
|
TAIL |
The last return statement | BEFORE |
|
THROW |
All throw statements | BEFORE |
|
INVOKE |
All method invocations |
BEFORE , AFTER
|
Method Target |
FIELD |
All field accesses |
BEFORE , AFTER
|
Field Target |
GETFIELD |
All field reads |
BEFORE , AFTER
|
Field Target |
PUTFIELD |
All field writes |
BEFORE , AFTER
|
Field Target |
NEW |
All object instantiations |
BEFORE , AFTER
|
Method Target/Descriptor/Class name |
OPCODE |
All instructions |
BEFORE , AFTER
|
Opcode name or value |
CONSTANT |
null /int /long /float /double /String /Type constant |
BEFORE , AFTER
|
Constant value |
Additional information about the built-in types:
New type
The NEW
type allows matching all object instantiations.
Examples:
//Class name with slashes
@CTarget(value = "NEW", target = "java/lang/String")
@CTarget(value = "NEW", target = "Ljava/lang/String;")
//Method target
@CTarget(value = "NEW", target = "java/lang/String.<init>(Ljava/lang/String;)V")
@CTarget(value = "NEW", target = "Ljava/lang/String;<init>(Ljava/lang/String;)V")
//Descriptor
@CTarget(value = "NEW", target = "(Ljava/lang/String;)V") //Be aware that this does not match the owner!
//Specific constructor
//The return type is the class name
@CTarget(value = "NEW", target = "(Ljava/lang/String;)Ljava/lang/String;")
Opcodes type
The OPCODE
type allows matching all instructions with a specific opcode.
Examples:
@CTarget(value = "OPCODE", target = "INVOKESTATIC")
@CTarget(value = "OPCODE", target = "184")
All Opcodes can be found in the Opcodes
class in the ASM library.
Constant type
The CONSTANT
type allows matching all ldc instructions with a specific constant value.
Syntax for the target
field:
Type | Syntax | Example |
---|---|---|
null |
null |
null |
int |
int <constant> |
int 1 |
long |
long <constant> |
long 2 |
float |
float <constant> |
float 3 |
double |
double <constant> |
double 4 |
String |
string <text> |
string Hello World |
Type |
type <descriptor> |
type Ljava/lang/String; |
Custom types can be created by implementing the IInjectionTarget
interface.
The List<AbstractInsnNode> getTargets(final Map<String, IInjectionTarget> injectionTargets, final MethodNode method, final CTarget target, final CSlice slice)
method needs to be implemented and should return a list of instructions that match the target.
The injectionTargets
parameter contains all available injection targets.
The method
parameter is the method that should be targeted.
The target
parameter is the target annotation which contains the target information.
The slice
parameter is the slice annotation which contains the slice information (optional).
//Target all INVOKESTATIC instructions
@CTarget(value = "OPCODE", target = "INVOKESTATIC")
//Target the second null constant
@CTarget(value = "CONSTANT", target = "null", ordinal = 1)
//Target the first String.equals() call
@CTarget(value = "INVOKE", target = "java/lang/String.equals(Ljava/lang/Object;)Z", ordinal = 0)
//Target the last return statement
@CTarget(value = "TAIL")
//Target the first field access
@CTarget(value = "FIELD", target = "java/lang/String.length:I", ordinal = 0)