public final class MethodEditor
extends java.lang.Object
A patch is simply a subclass of MethodEditor.Patch, representing a code sequence to insert into the method. Each patch class implements one method, emitTo(), which writes the patch code into the code stream using the provided MethodEditor.Output instance. Anonymous inner classes are very useful for writing patches.
Patches can be inserted at the following points:
MethodEditor relies on labels. A label is an integer representing a point in the code. Labels are valid only during a single pass; at the end of each pass, instructions are reordered and old labels become invalid. At the beginning of a pass every instruction in the instructions array is labelled with the index of that instruction in the array. During instrumentation new labels can be allocated by calling MethodEditor.allocateLabel(); control instructions can be created referring to these new labels or the existing labels. At the end of a pass, as patch code is spliced into the method body, all instructions are updated to refer to the new labels which are simply the indices of instructions in the instruction array.
| Modifier and Type | Class and Description |
|---|---|
static class |
MethodEditor.Output
Output is the interface that patches use to emit their code into a method body.
|
static class |
MethodEditor.Patch
This class is subclassed for each kind of patch that you want to apply.
|
static class |
MethodEditor.Visitor
A specialized Instruction.Visitor providing convenience methods for inserting patches.
|
| Constructor and Description |
|---|
MethodEditor(Instruction[] instructions,
ExceptionHandler[][] handlers,
int[] instructionsToBytecodes)
Build an editor for specific method data.
|
MethodEditor(MethodData info)
Build an editor for the given method.
|
| Modifier and Type | Method and Description |
|---|---|
void |
addInstructionExceptionHandler(int i,
java.lang.String catchClass,
MethodEditor.Patch p)
An "instruction exception handler" handles exceptions generated by a specific instruction
(including patch code that may be inserted before, after, or instead of the instruction in this
pass).
|
void |
addMethodExceptionHandler(java.lang.String catchClass,
MethodEditor.Patch p)
A "method exception handler" handles exceptions generated anywhere in the method.
|
int |
allocateLabel()
Allocate a fresh label.
|
boolean |
applyPatches()
This method finishes a pass.
|
void |
beginPass()
This must be called before inserting any patches.
|
void |
endPass()
This must be called after inserting any patches.
|
MethodData |
getData() |
ExceptionHandler[][] |
getHandlers() |
IInstruction[] |
getInstructions() |
int[] |
getInstructionsToBytecodes() |
void |
insertAfter(int i,
MethodEditor.Patch p)
Insert code to be executed after the instruction.
|
void |
insertAfterBody(MethodEditor.Patch p)
This method inserts code that will be placed after the method body.
|
void |
insertAtStart(MethodEditor.Patch p)
Insert code to be executed whenever the method is entered.
|
void |
insertBefore(int i,
MethodEditor.Patch p)
Insert code to be executed before the instruction.
|
void |
replaceWith(int i,
MethodEditor.Patch p)
Insert code to replace the instruction.
|
void |
visitInstructions(MethodEditor.Visitor v)
Apply Visitor v to each instruction in the code, for the purpose of patching the code.
|
public MethodEditor(MethodData info)
java.lang.IllegalArgumentException - if info is nullpublic MethodEditor(Instruction[] instructions, ExceptionHandler[][] handlers, int[] instructionsToBytecodes)
public ExceptionHandler[][] getHandlers()
public IInstruction[] getInstructions()
public int[] getInstructionsToBytecodes()
public void beginPass()
public void endPass()
public int allocateLabel()
throws java.lang.IllegalArgumentException
java.lang.IllegalArgumentExceptionpublic void insertAtStart(MethodEditor.Patch p)
When multiple 'start' patches are given, the last one added is first in execution order.
java.lang.IllegalArgumentException - if p is nullpublic void insertBefore(int i,
MethodEditor.Patch p)
When multiple 'before' patches are given, the last one added is first in execution order.
java.lang.IllegalArgumentException - if p is nullpublic void insertAfter(int i,
MethodEditor.Patch p)
When multiple 'after' patches are given, the last one added is LAST in execution order.
public void replaceWith(int i,
MethodEditor.Patch p)
throws java.lang.NullPointerException
Multiple replacements are not allowed.
java.lang.NullPointerException - if p is nulljava.lang.IllegalArgumentException - if p is nullpublic void addInstructionExceptionHandler(int i,
java.lang.String catchClass,
MethodEditor.Patch p)
If multiple instruction exception handlers are given, then the last one added handles the exception first; if an exception is rethrown, then the next-to-last one added handles that exception, etc.
public void addMethodExceptionHandler(java.lang.String catchClass,
MethodEditor.Patch p)
If multiple method exception handlers are given, then the last one added handles the exception first; if an exception is rethrown, then the next-to-last one added handles that exception, etc.
public void insertAfterBody(MethodEditor.Patch p)
java.lang.IllegalArgumentException - if p is nullpublic MethodData getData()
public boolean applyPatches()
throws java.lang.IllegalArgumentException
If no patches were issued, we don't need to do anything at all; this case is detected quickly and no updates are made.
java.lang.IllegalArgumentExceptionpublic void visitInstructions(MethodEditor.Visitor v)