An injection point specifies a position //inside the body// of a target method to operate on. Where to ''@Inject'', which method to ''@Redirect'', etc. ====== @At ====== Injection points are created with the ''@At'' annotation, which takes a ''String value'' consisting of one of the following: ^ name ^ position ^ ''target''? ^ ''ordinal''? ^ ''opcode''? ^ ''args''? ^ | ''HEAD'' | top of a method | | | | | | ''CTOR_HEAD'' | top of a constructor, after initializers and ''super''/''this'' delegation | | | | | | ''RETURN'' | before a ''return'' | | yes | | | | ''TAIL'' | before the //final// ''return'' | | | | | | ''LOAD'' | before reading a local variable or argument | | yes | | | | ''STORE'' | after writing a local variable or argument | | yes | | | | ''NEW'' | before an object creation | yes | yes | | | | ''INVOKE'' | before a method invocation | yes | yes | | | | ''INVOKE_ASSIGN'' | //after// a method invocation, and after it's assigned to a local | yes | yes | | | | ''FIELD'' | before getting or setting a field | yes | yes | yes | | | ''CONSTANT'' | before a literal | | yes | | yes | | ''INVOKE_STRING'' | before a method invocation with a single string literal arg | yes | yes | | yes | | ''JUMP'' | before a jump | | yes | yes | | Each of these injection points refers to //every// point that matches its description. So, it's often necessary to narrow down the results with the additional specifiers I've noted at the end of the table. * ''String target'' The //fully-qualified// [[target-selector|target selector]] to the field or method to match. * ''int ordinal'' The index of the desired match in the list of potential matches. ** ''int opcode'' The specific opcode to match. .. ''FIELD'' can match ''GETFIELD'', ''PUTFIELD'', ''GETSTATIC'', or ''PUTSTATIC''. .. ''JUMP'' can match any ''IF'' variant, ''GOTO'', or ''JSR''. .. ''org.objectweb.asm.Opcodes'' will help in specifying opcodes by name, and [[https://docs.oracle.com/javase/specs/jvms/se17/html/jvms-6.html|JVM Spec Chapter 6. The Java Virtual Machine Instruction Set]] will help in determining the meaning of each one. ** ''String[] args'' are special arguments specific to that particular injection point. contents are specified as strings of the form ''"="'' .. ''INVOKE_STRING'' accepts ''ldc='' to filter on the specific value of the string literal. .. ''CONSTANT'' accepts ''intValue'', ''longValue'', ''floatValue'', ''doubleValue'', ''stringValue'' to filter on type and value, ''nullValue=true'' to filter on null, ''classValue='' to filter on class, and ''expandZeroConditions=(GREATER|LESS)_THAN_(OR_EQUAL_TO_)ZERO'' to find the zero constant in comparisons that might cause it to be optimized out. It also might be necessary to shift the injection point back or forward instruction-wise. ''@At'' takes ''At.Shift shift'', which can be ''AFTER'', ''BEFORE'' (note that most injection points are //already// directly before their target. this will shift them one //further//), or ''BY'', which requires the additional argument ''int by'', an offset. ====== @Slice ====== Injection points are also used to limit the //region of the body// to search. The annotations that accept ''at = @At(...)'' also optionally accept ''slice = @Slice(from = @At(...), to = @At(...))''. If present, a slice will prevent injection points outside it from being matched.