Package com.tonic.analysis
Class CodeWriter
- java.lang.Object
-
- com.tonic.analysis.CodeWriter
-
public class CodeWriter extends Object
A class for analyzing and modifying the bytecode of a MethodEntry.
-
-
Nested Class Summary
Nested Classes Modifier and Type Class Description static classCodeWriter.ClonedRangeA cloned instruction range.
-
Constructor Summary
Constructors Constructor Description CodeWriter(MethodEntry methodEntry)Constructs a CodeWriter for the given MethodEntry.
-
Method Summary
All Methods Instance Methods Concrete Methods Modifier and Type Method Description voidaccept(AbstractBytecodeVisitor visitor)Accepts a BytecodeVisitor to traverse and operate on the instructions.voidanalyze()Updates maxStack and maxLocals from the current bytecode, using a simplified analysis that does not cover every case.voidappendInstruction(Instruction newInstr)Appends a new instruction to the end of the bytecode.List<Instruction>cloneRange(Instruction from, Instruction to, int localOffset)Clones a contiguous instruction range[from, to]into a fresh list, shifting every local index bylocalOffset.CodeWriter.ClonedRangecloneRangeWithTargets(Instruction from, Instruction to, int localOffset, ConstPool targetPool, IntUnaryOperator cpRemap)AscloneRange(Instruction, Instruction, int), but carries branch/switch targets by identity and remaps constant-pool references intotargetPool.voidcomputeFrames()Computes and installs StackMapTable frames after awrite(); a valid existing table is preserved when the bytecode was not modified.intcomputeMaxStack()Computesmax_stackover the control-flow graph (viaFrameGenerator) and raises the method's value if the linear estimate under-counts - correct for loops, joins, and handler entry states where a textual scan can miss the true peak.booleanendsWithReturn()Checks if the bytecode ends with a return instruction.intfindInstructionIndexForOffset(int targetOffset)Finds the instruction index that contains or follows the given bytecode offset.voidforceComputeFrames()Recomputes the StackMapTable unconditionally, ignoring the modified flag and any existing valid table.Map<Instruction,List<Instruction>>getBranchTargets()byte[]getBytecode()intgetBytecodeSize()Returns the size of the bytecode array in bytes.CodeAttributegetCodeAttribute()ConstPoolgetConstPool()InstructiongetInstructionAt(int index)Gets the instruction at a specific sequential index (0, 1, 2, ...).intgetInstructionCount()Returns the total number of instructions in this method.intgetInstructionIndex(int offset)Gets the sequential instruction index for the instruction at the given bytecode offset.List<Instruction>getInstructionList()Returns a fresh, bytecode-ordered, random-access snapshot of the instructions.Iterable<Instruction>getInstructions()Iterates over all instructions.intgetMaxLocals()intgetMaxStack()MethodEntrygetMethodEntry()intgetOffsetAt(int index)Gets the bytecode offset for the instruction at a specific sequential index.booleanhasValidStackMapTable()Checks if the CodeAttribute has a valid StackMapTable.voidinsertAfter(Instruction handle, CodeWriter.ClonedRange block)Inserts a cloned range after the handle, carrying its targets + exception regions by identity.voidinsertAfter(Instruction handle, CodeWriter.ClonedRange block, Map<String,Instruction> externalBindings)AsinsertAfter(Instruction, ClonedRange)but binds external labels to host targets first.voidinsertAfter(Instruction handle, Instruction newInstr)InsertsnewInstrimmediately after the given instruction handle.voidinsertAfter(Instruction handle, List<Instruction> block)Inserts a block of instructions immediately after the handle.ALoadInstructioninsertALoad(int offset, int index)Inserts an ALOAD instruction at the specified bytecode offset.AStoreInstructioninsertAStore(int offset, int index)Inserts an ASTORE instruction at the specified bytecode offset.voidinsertBefore(Instruction handle, CodeWriter.ClonedRange block)Inserts a cloned range before the handle, carrying its targets + exception regions by identity.voidinsertBefore(Instruction handle, CodeWriter.ClonedRange block, Map<String,Instruction> externalBindings)AsinsertBefore(Instruction, ClonedRange)but binds external labels to host targets first.voidinsertBefore(Instruction handle, Instruction newInstr)InsertsnewInstrimmediately before the given instruction handle.voidinsertBefore(Instruction handle, List<Instruction> block)Inserts a block of instructions (e.g.voidinsertChainBefore(Instruction at, List<CodeWriter.ClonedRange> bodies)Splices several cloned bodies beforeat, chaining them so each body's continuation exits (e.g.DLoadInstructioninsertDLoad(int offset, int index)Inserts a DLOAD instruction at the specified bytecode offset.DStoreInstructioninsertDStore(int offset, int index)Inserts a DSTORE instruction at the specified bytecode offset.FLoadInstructioninsertFLoad(int offset, int index)Inserts an FLOAD instruction at the specified bytecode offset.FStoreInstructioninsertFStore(int offset, int index)Inserts an FSTORE instruction at the specified bytecode offset.GetFieldInstructioninsertGetField(int offset, int fieldRefIndex)Inserts a GETFIELD instruction at the specified bytecode offset.GetFieldInstructioninsertGetStatic(int offset, int fieldRefIndex)Inserts a GETSTATIC instruction at the specified bytecode offset.GotoInstructioninsertGoto(int offset, short branchOffset)Inserts a GOTO instruction at the specified bytecode offset with a signed short branch offset.GotoInstructioninsertGotoW(int offset, int branchOffset)Inserts a GOTO_W instruction at the specified bytecode offset with a 32-bit branch offset.IIncInstructioninsertIInc(int offset, int varIndex, int increment)Inserts an IINC instruction at the specified bytecode offset.ILoadInstructioninsertILoad(int offset, int index)Inserts an ILOAD instruction at the specified bytecode offset.voidinsertInstruction(int offset, Instruction newInstr)Inserts an instruction before whatever instruction currently sits atoffset(or appends it whenoffset == code length).InvokeDynamicInstructioninsertInvokeDynamic(int offset, int cpIndex)Inserts an INVOKEDYNAMIC instruction at the specified bytecode offset.InvokeInterfaceInstructioninsertInvokeInterface(int offset, int interfaceMethodRefIndex, int count)Inserts an INVOKEINTERFACE instruction at the specified bytecode offset.InvokeSpecialInstructioninsertInvokeSpecial(int offset, int methodRefIndex)Inserts an INVOKESPECIAL instruction at the specified bytecode offset.InvokeStaticInstructioninsertInvokeStatic(int offset, int methodRefIndex)Inserts an INVOKESTATIC instruction at the specified bytecode offset.InvokeVirtualInstructioninsertInvokeVirtual(int offset, int methodRefIndex)Inserts an INVOKEVIRTUAL instruction at the specified bytecode offset.IStoreInstructioninsertIStore(int offset, int index)Inserts an ISTORE instruction at the specified bytecode offset.LdcInstructioninsertLDC(int offset, int constantPoolIndex)Inserts an LDC instruction at the specified bytecode offset.LdcWInstructioninsertLDCW(int offset, int constantPoolIndex)Inserts an LDC_W instruction at the specified bytecode offset.LLoadInstructioninsertLLoad(int offset, int index)Inserts an LLOAD instruction at the specified bytecode offset.LookupSwitchInstructioninsertLookupSwitch(int offset, int padding, int defaultOffset, int npairs, Map<Integer,Integer> matchOffsets)Inserts a LOOKUPSWITCH instruction at the specified bytecode offset.LStoreInstructioninsertLStore(int offset, int index)Inserts an LSTORE instruction at the specified bytecode offset.NewObjectInstructioninsertNew(int offset, int classRefIndex)Inserts a NEW instruction at the specified bytecode offset.PutFieldInstructioninsertPutField(int offset, int fieldRefIndex)Inserts a PUTFIELD instruction at the specified bytecode offset.PutFieldInstructioninsertPutStatic(int offset, int fieldRefIndex)Inserts a PUTSTATIC instruction at the specified bytecode offset.TableSwitchInstructioninsertTableSwitch(int offset, int padding, int defaultOffset, int low, int high, Map<Integer,Integer> jumpOffsets)Inserts a TABLESWITCH instruction at the specified bytecode offset.booleanisModified()voidreload()Re-reads this writer's instruction list from the underlying CodeAttribute.voidremoveInstruction(Instruction handle)Removes an instruction, identified by handle (object identity), and relinks the method.voidremoveInstructions(Collection<Instruction> handles)Removes many instructions in a single relink, linear in the method size rather than quadratic in the number of removals.voidreplaceBody(CodeWriter.ClonedRange block)Replaces the body with a cloned range, carrying its targets + exception regions by identity.voidreplaceBody(CodeWriter.ClonedRange block, List<ExceptionTableEntry> exceptions)Replaces the body with a cloned range plus an explicit exception table (targets by identity).voidreplaceBody(List<Instruction> body)Replaces this method's entire instruction stream withbody(e.g.voidreplaceBody(List<Instruction> body, List<ExceptionTableEntry> exceptions)AsreplaceBody(List)but with an exception table whose entry PCs are interpreted againstbody's layout, bound by identity so regenerated frames cover the handler blocks.voidreplaceInstruction(Instruction handle, Instruction replacement)Replaces an instruction (by handle) with another, preserving control flow.voidreplaceInstructions(Map<Instruction,Instruction> replacements)Replaces many instructions in a single relink, preserving control flow exactly asreplaceInstruction(com.tonic.analysis.instruction.Instruction, com.tonic.analysis.instruction.Instruction)does per element.voidsetBranchTarget(Instruction branch, Instruction target)Registers the target of a (typically newly created) branch instruction by identity, so that the relink pass can compute its relative offset.voidsetSwitchTargets(Instruction switchInstr, Instruction defaultTarget, List<Instruction> caseTargets)Registers the targets of a switch instruction by identity: the default target followed by one target per case in case order.CodeWriter.ClonedRangetoClonedRange()Snapshots this writer's full instruction list and its by-identity branch/switch targets into aCodeWriter.ClonedRange.CodeWriter.ClonedRangetoClonedRange(List<ExceptionTableEntry> regionEntries)AstoClonedRange()but also carries exception regions.CodeWriter.ClonedRangetoClonedRange(List<ExceptionTableEntry> regionEntries, Map<String,List<Integer>> externalOffsets, List<Integer> continuationOffsets)AstoClonedRange(List)but also records branches whose targets lie outside the snippet.voidwrite()Writes the modified bytecode back to the MethodEntry.voidwriteWithoutMaxStack()Serializes the (already-relinked) instructions back to the method WITHOUT the dataflow max-stack pass.
-
-
-
Constructor Detail
-
CodeWriter
public CodeWriter(MethodEntry methodEntry)
Constructs a CodeWriter for the given MethodEntry.- Parameters:
methodEntry- The MethodEntry to manipulate.
-
-
Method Detail
-
getMethodEntry
public MethodEntry getMethodEntry()
- Returns:
- the method entry
-
getCodeAttribute
public CodeAttribute getCodeAttribute()
- Returns:
- the code attribute
-
getBytecode
public byte[] getBytecode()
- Returns:
- the bytecode
-
getConstPool
public ConstPool getConstPool()
- Returns:
- the const pool
-
getBranchTargets
public Map<Instruction,List<Instruction>> getBranchTargets()
- Returns:
- the branch targets
-
getMaxStack
public int getMaxStack()
- Returns:
- the max stack
-
getMaxLocals
public int getMaxLocals()
- Returns:
- the max locals
-
isModified
public boolean isModified()
- Returns:
- true if the bytecode has been modified since loading
-
getInstructions
public Iterable<Instruction> getInstructions()
Iterates over all instructions.- Returns:
- An Iterable of Instructions.
-
getInstructionList
public List<Instruction> getInstructionList()
Returns a fresh, bytecode-ordered, random-access snapshot of the instructions.- Returns:
- the instructions in offset order
-
getInstructionCount
public int getInstructionCount()
Returns the total number of instructions in this method.- Returns:
- instruction count
-
getInstructionIndex
public int getInstructionIndex(int offset)
Gets the sequential instruction index for the instruction at the given bytecode offset.- Parameters:
offset- The bytecode offset- Returns:
- The sequential instruction index, or -1 if no instruction at that offset
-
getInstructionAt
public Instruction getInstructionAt(int index)
Gets the instruction at a specific sequential index (0, 1, 2, ...).- Parameters:
index- The sequential instruction index- Returns:
- The instruction at that index, or null if out of bounds
-
getOffsetAt
public int getOffsetAt(int index)
Gets the bytecode offset for the instruction at a specific sequential index.- Parameters:
index- The sequential instruction index- Returns:
- The bytecode offset, or -1 if out of bounds
-
findInstructionIndexForOffset
public int findInstructionIndexForOffset(int targetOffset)
Finds the instruction index that contains or follows the given bytecode offset.- Parameters:
targetOffset- The bytecode offset to search for- Returns:
- The instruction index, or -1 if not found
-
insertInstruction
public void insertInstruction(int offset, Instruction newInstr)Inserts an instruction before whatever instruction currently sits atoffset(or appends it whenoffset == code length).- Parameters:
offset- the bytecode offset of the instruction to insert beforenewInstr- the new instruction to insert
-
removeInstruction
public void removeInstruction(Instruction handle)
Removes an instruction, identified by handle (object identity), and relinks the method.- Parameters:
handle- the instruction to remove (an object currently in this method)
-
replaceInstruction
public void replaceInstruction(Instruction handle, Instruction replacement)
Replaces an instruction (by handle) with another, preserving control flow.- Parameters:
handle- the instruction to replacereplacement- the new instruction
-
replaceInstructions
public void replaceInstructions(Map<Instruction,Instruction> replacements)
Replaces many instructions in a single relink, preserving control flow exactly asreplaceInstruction(com.tonic.analysis.instruction.Instruction, com.tonic.analysis.instruction.Instruction)does per element.- Parameters:
replacements- existing handle → replacement instruction
-
removeInstructions
public void removeInstructions(Collection<Instruction> handles)
Removes many instructions in a single relink, linear in the method size rather than quadratic in the number of removals.- Parameters:
handles- the instruction handles to remove
-
replaceBody
public void replaceBody(List<Instruction> body)
Replaces this method's entire instruction stream withbody(e.g. a cloned/grafted body), then relinks.- Parameters:
body- the new instruction stream, in order
-
replaceBody
public void replaceBody(List<Instruction> body, List<ExceptionTableEntry> exceptions)
AsreplaceBody(List)but with an exception table whose entry PCs are interpreted againstbody's layout, bound by identity so regenerated frames cover the handler blocks.- Parameters:
body- the new instruction stream, in orderexceptions- the exception-table entries (catch_type indices in this method's pool)
-
replaceBody
public void replaceBody(CodeWriter.ClonedRange block)
Replaces the body with a cloned range, carrying its targets + exception regions by identity.- Parameters:
block- the cloned range to install as the new body
-
replaceBody
public void replaceBody(CodeWriter.ClonedRange block, List<ExceptionTableEntry> exceptions)
Replaces the body with a cloned range plus an explicit exception table (targets by identity).- Parameters:
block- the cloned range to install as the new bodyexceptions- the exception-table entries, PCs against the block's layout
-
insertBefore
public void insertBefore(Instruction handle, CodeWriter.ClonedRange block)
Inserts a cloned range before the handle, carrying its targets + exception regions by identity.- Parameters:
handle- the instruction to insert beforeblock- the cloned range to splice
-
insertBefore
public void insertBefore(Instruction handle, CodeWriter.ClonedRange block, Map<String,Instruction> externalBindings)
AsinsertBefore(Instruction, ClonedRange)but binds external labels to host targets first.- Parameters:
handle- the instruction to insert beforeblock- the cloned range to spliceexternalBindings- the host instruction to bind each external label to
-
insertAfter
public void insertAfter(Instruction handle, CodeWriter.ClonedRange block)
Inserts a cloned range after the handle, carrying its targets + exception regions by identity.- Parameters:
handle- the instruction to insert afterblock- the cloned range to splice
-
insertAfter
public void insertAfter(Instruction handle, CodeWriter.ClonedRange block, Map<String,Instruction> externalBindings)
AsinsertAfter(Instruction, ClonedRange)but binds external labels to host targets first.- Parameters:
handle- the instruction to insert afterblock- the cloned range to spliceexternalBindings- the host instruction to bind each external label to
-
insertChainBefore
public void insertChainBefore(Instruction at, List<CodeWriter.ClonedRange> bodies)
Splices several cloned bodies beforeat, chaining them so each body's continuation exits (e.g. fromCodeWriter.ClonedRange.redirectReturns()) fall through into the next body's entry and the last body's intoat.- Parameters:
at- the instruction the last body falls through intobodies- the cloned bodies to splice, in execution order
-
insertBefore
public void insertBefore(Instruction handle, Instruction newInstr)
InsertsnewInstrimmediately before the given instruction handle.- Parameters:
handle- the instruction to insert beforenewInstr- the instruction to insert
-
insertBefore
public void insertBefore(Instruction handle, List<Instruction> block)
Inserts a block of instructions (e.g. a cloned method body) immediately before the handle.- Parameters:
handle- the instruction to insert beforeblock- the instructions, in order
-
insertAfter
public void insertAfter(Instruction handle, Instruction newInstr)
InsertsnewInstrimmediately after the given instruction handle.- Parameters:
handle- the instruction to insert afternewInstr- the instruction to insert
-
insertAfter
public void insertAfter(Instruction handle, List<Instruction> block)
Inserts a block of instructions immediately after the handle.- Parameters:
handle- the instruction to insert afterblock- the instructions, in order
-
setBranchTarget
public void setBranchTarget(Instruction branch, Instruction target)
Registers the target of a (typically newly created) branch instruction by identity, so that the relink pass can compute its relative offset.- Parameters:
branch- the branch instructiontarget- the instruction it jumps to
-
setSwitchTargets
public void setSwitchTargets(Instruction switchInstr, Instruction defaultTarget, List<Instruction> caseTargets)
Registers the targets of a switch instruction by identity: the default target followed by one target per case in case order.- Parameters:
switchInstr- the switch instructiondefaultTarget- the default branch targetcaseTargets- one target per case, in case order
-
toClonedRange
public CodeWriter.ClonedRange toClonedRange()
Snapshots this writer's full instruction list and its by-identity branch/switch targets into aCodeWriter.ClonedRange.- Returns:
- the snapshot, carrying no exception regions
-
toClonedRange
public CodeWriter.ClonedRange toClonedRange(List<ExceptionTableEntry> regionEntries)
AstoClonedRange()but also carries exception regions.- Parameters:
regionEntries- the exception-table entries to carry, PCs against this writer's layout- Returns:
- the snapshot
-
toClonedRange
public CodeWriter.ClonedRange toClonedRange(List<ExceptionTableEntry> regionEntries, Map<String,List<Integer>> externalOffsets, List<Integer> continuationOffsets)
AstoClonedRange(List)but also records branches whose targets lie outside the snippet.- Parameters:
regionEntries- the exception-table entries to carry, PCs against this writer's layoutexternalOffsets- branch offsets per external label name, bound at splice timecontinuationOffsets- branch offsets that fall through into the host- Returns:
- the snapshot
-
cloneRange
public List<Instruction> cloneRange(Instruction from, Instruction to, int localOffset)
Clones a contiguous instruction range[from, to]into a fresh list, shifting every local index bylocalOffset.- Parameters:
from- first instruction of the range (a handle in this method)to- last instruction of the range (inclusive)localOffset- value added to every local-variable index in the clone- Returns:
- the cloned instructions, in order
-
cloneRangeWithTargets
public CodeWriter.ClonedRange cloneRangeWithTargets(Instruction from, Instruction to, int localOffset, ConstPool targetPool, IntUnaryOperator cpRemap)
AscloneRange(Instruction, Instruction, int), but carries branch/switch targets by identity and remaps constant-pool references intotargetPool.- Parameters:
from- first instruction (inclusive)to- last instruction (inclusive)localOffset- value added to every local-variable indextargetPool- the constant pool the clones will live in (null to keep this method's pool)cpRemap- old cp index → new cp index, or null for no remap- Returns:
- the cloned range with identity-tracked targets
-
computeMaxStack
public int computeMaxStack()
Computesmax_stackover the control-flow graph (viaFrameGenerator) and raises the method's value if the linear estimate under-counts - correct for loops, joins, and handler entry states where a textual scan can miss the true peak.- Returns:
- the resulting max_stack
-
analyze
public void analyze()
Updates maxStack and maxLocals from the current bytecode, using a simplified analysis that does not cover every case.
-
write
public void write() throws IOExceptionWrites the modified bytecode back to the MethodEntry.- Throws:
IOException- If an I/O error occurs.
-
writeWithoutMaxStack
public void writeWithoutMaxStack()
Serializes the (already-relinked) instructions back to the method WITHOUT the dataflow max-stack pass.
-
hasValidStackMapTable
public boolean hasValidStackMapTable()
Checks if the CodeAttribute has a valid StackMapTable.- Returns:
- true if a StackMapTable exists with frames
-
computeFrames
public void computeFrames()
Computes and installs StackMapTable frames after awrite(); a valid existing table is preserved when the bytecode was not modified.
-
forceComputeFrames
public void forceComputeFrames()
Recomputes the StackMapTable unconditionally, ignoring the modified flag and any existing valid table.
-
getBytecodeSize
public int getBytecodeSize()
Returns the size of the bytecode array in bytes.- Returns:
- bytecode size
-
endsWithReturn
public boolean endsWithReturn()
Checks if the bytecode ends with a return instruction.- Returns:
- true if ends with return, false otherwise
-
insertInvokeVirtual
public InvokeVirtualInstruction insertInvokeVirtual(int offset, int methodRefIndex)
Inserts an INVOKEVIRTUAL instruction at the specified bytecode offset.- Parameters:
offset- The bytecode offset to insert the instruction at.methodRefIndex- The index into the constant pool for the method reference.- Returns:
- the inserted instruction
-
insertInvokeSpecial
public InvokeSpecialInstruction insertInvokeSpecial(int offset, int methodRefIndex)
Inserts an INVOKESPECIAL instruction at the specified bytecode offset.- Parameters:
offset- The bytecode offset to insert the instruction at.methodRefIndex- The index into the constant pool for the method reference.- Returns:
- the inserted instruction
-
insertInvokeStatic
public InvokeStaticInstruction insertInvokeStatic(int offset, int methodRefIndex)
Inserts an INVOKESTATIC instruction at the specified bytecode offset.- Parameters:
offset- The bytecode offset to insert the instruction at.methodRefIndex- The index into the constant pool for the method reference.- Returns:
- the inserted instruction
-
insertInvokeInterface
public InvokeInterfaceInstruction insertInvokeInterface(int offset, int interfaceMethodRefIndex, int count)
Inserts an INVOKEINTERFACE instruction at the specified bytecode offset.- Parameters:
offset- The bytecode offset to insert the instruction at.interfaceMethodRefIndex- The index into the constant pool for the interface method reference.count- The count of arguments for the interface method.- Returns:
- the inserted instruction
-
insertInvokeDynamic
public InvokeDynamicInstruction insertInvokeDynamic(int offset, int cpIndex)
Inserts an INVOKEDYNAMIC instruction at the specified bytecode offset.- Parameters:
offset- The bytecode offset to insert the instruction at.cpIndex- The constant pool index to the CONSTANT_InvokeDynamic_info entry.- Returns:
- the inserted instruction
-
insertALoad
public ALoadInstruction insertALoad(int offset, int index)
Inserts an ALOAD instruction at the specified bytecode offset.- Parameters:
offset- The bytecode offset to insert the instruction at.index- The local variable index to load from.- Returns:
- the inserted instruction
-
insertAStore
public AStoreInstruction insertAStore(int offset, int index)
Inserts an ASTORE instruction at the specified bytecode offset.- Parameters:
offset- The bytecode offset to insert the instruction at.index- The local variable index to store into.- Returns:
- the inserted instruction
-
insertGetStatic
public GetFieldInstruction insertGetStatic(int offset, int fieldRefIndex)
Inserts a GETSTATIC instruction at the specified bytecode offset.- Parameters:
offset- The bytecode offset to insert the instruction at.fieldRefIndex- The index into the constant pool for the field reference.- Returns:
- the inserted instruction
-
insertGetField
public GetFieldInstruction insertGetField(int offset, int fieldRefIndex)
Inserts a GETFIELD instruction at the specified bytecode offset.- Parameters:
offset- The bytecode offset to insert the instruction at.fieldRefIndex- The index into the constant pool for the field reference.- Returns:
- the inserted instruction
-
insertPutStatic
public PutFieldInstruction insertPutStatic(int offset, int fieldRefIndex)
Inserts a PUTSTATIC instruction at the specified bytecode offset.- Parameters:
offset- The bytecode offset to insert the instruction at.fieldRefIndex- The index into the constant pool for the field reference.- Returns:
- the inserted instruction
-
insertPutField
public PutFieldInstruction insertPutField(int offset, int fieldRefIndex)
Inserts a PUTFIELD instruction at the specified bytecode offset.- Parameters:
offset- The bytecode offset to insert the instruction at.fieldRefIndex- The index into the constant pool for the field reference.- Returns:
- the inserted instruction
-
insertILoad
public ILoadInstruction insertILoad(int offset, int index)
Inserts an ILOAD instruction at the specified bytecode offset.- Parameters:
offset- The bytecode offset to insert the instruction at.index- The local variable index to load from.- Returns:
- the inserted instruction
-
insertIStore
public IStoreInstruction insertIStore(int offset, int index)
Inserts an ISTORE instruction at the specified bytecode offset.- Parameters:
offset- The bytecode offset to insert the instruction at.index- The local variable index to store into.- Returns:
- the inserted instruction
-
insertLLoad
public LLoadInstruction insertLLoad(int offset, int index)
Inserts an LLOAD instruction at the specified bytecode offset.- Parameters:
offset- The bytecode offset to insert the instruction at.index- The local variable index to load from.- Returns:
- the inserted instruction
-
insertLStore
public LStoreInstruction insertLStore(int offset, int index)
Inserts an LSTORE instruction at the specified bytecode offset.- Parameters:
offset- The bytecode offset to insert the instruction at.index- The local variable index to store into.- Returns:
- the inserted instruction
-
insertFLoad
public FLoadInstruction insertFLoad(int offset, int index)
Inserts an FLOAD instruction at the specified bytecode offset.- Parameters:
offset- The bytecode offset to insert the instruction at.index- The local variable index to load from.- Returns:
- the inserted instruction
-
insertFStore
public FStoreInstruction insertFStore(int offset, int index)
Inserts an FSTORE instruction at the specified bytecode offset.- Parameters:
offset- The bytecode offset to insert the instruction at.index- The local variable index to store into.- Returns:
- the inserted instruction
-
insertDLoad
public DLoadInstruction insertDLoad(int offset, int index)
Inserts a DLOAD instruction at the specified bytecode offset.- Parameters:
offset- The bytecode offset to insert the instruction at.index- The local variable index to load from.- Returns:
- the inserted instruction
-
insertDStore
public DStoreInstruction insertDStore(int offset, int index)
Inserts a DSTORE instruction at the specified bytecode offset.- Parameters:
offset- The bytecode offset to insert the instruction at.index- The local variable index to store into.- Returns:
- the inserted instruction
-
insertIInc
public IIncInstruction insertIInc(int offset, int varIndex, int increment)
Inserts an IINC instruction at the specified bytecode offset.- Parameters:
offset- The bytecode offset to insert the instruction at.varIndex- The local variable index to increment.increment- The constant by which to increment the variable.- Returns:
- the inserted instruction
-
insertGoto
public GotoInstruction insertGoto(int offset, short branchOffset)
Inserts a GOTO instruction at the specified bytecode offset with a signed short branch offset.- Parameters:
offset- The bytecode offset to insert the GOTO instruction at.branchOffset- The signed short branch offset relative to the GOTO instruction.- Returns:
- the inserted instruction
-
insertGotoW
public GotoInstruction insertGotoW(int offset, int branchOffset)
Inserts a GOTO_W instruction at the specified bytecode offset with a 32-bit branch offset.- Parameters:
offset- The bytecode offset to insert the GOTO_W instruction at.branchOffset- The signed 32-bit branch offset relative to the GOTO_W instruction.- Returns:
- the inserted instruction
- Throws:
IllegalArgumentException- If the specified offset is invalid.
-
insertNew
public NewObjectInstruction insertNew(int offset, int classRefIndex)
Inserts a NEW instruction at the specified bytecode offset.- Parameters:
offset- The bytecode offset to insert the instruction at.classRefIndex- The index into the constant pool for the class reference.- Returns:
- the inserted instruction
-
insertLDC
public LdcInstruction insertLDC(int offset, int constantPoolIndex)
Inserts an LDC instruction at the specified bytecode offset.- Parameters:
offset- The bytecode offset to insert the instruction at.constantPoolIndex- The index into the constant pool for the constant.- Returns:
- the inserted instruction
-
insertLDCW
public LdcWInstruction insertLDCW(int offset, int constantPoolIndex)
Inserts an LDC_W instruction at the specified bytecode offset.- Parameters:
offset- The bytecode offset to insert the instruction at.constantPoolIndex- The 2-byte index into the constant pool for the constant.- Returns:
- the inserted instruction
-
insertTableSwitch
public TableSwitchInstruction insertTableSwitch(int offset, int padding, int defaultOffset, int low, int high, Map<Integer,Integer> jumpOffsets)
Inserts a TABLESWITCH instruction at the specified bytecode offset.- Parameters:
offset- The bytecode offset to insert the instruction at.padding- The number of padding bytes (0-3 for 4-byte alignment).defaultOffset- The branch target offset if no key matches.low- The lowest key value.high- The highest key value.jumpOffsets- The map of key to branch target offsets.- Returns:
- The created TableSwitchInstruction.
-
insertLookupSwitch
public LookupSwitchInstruction insertLookupSwitch(int offset, int padding, int defaultOffset, int npairs, Map<Integer,Integer> matchOffsets)
Inserts a LOOKUPSWITCH instruction at the specified bytecode offset.- Parameters:
offset- The bytecode offset to insert the instruction at.padding- The number of padding bytes (0-3 for 4-byte alignment).defaultOffset- The default branch target offset.npairs- The number of key-offset pairs.matchOffsets- The map of keys to branch target offsets.- Returns:
- The created LookupSwitchInstruction.
-
appendInstruction
public void appendInstruction(Instruction newInstr)
Appends a new instruction to the end of the bytecode.- Parameters:
newInstr- The Instruction to append.
-
accept
public void accept(AbstractBytecodeVisitor visitor)
Accepts a BytecodeVisitor to traverse and operate on the instructions.- Parameters:
visitor- The BytecodeVisitor implementation.
-
reload
public void reload()
Re-reads this writer's instruction list from the underlying CodeAttribute.
-
-